26
26
import os .path as op
27
27
import re
28
28
import shutil
29
+ import errno
29
30
from shutil import rmtree
30
31
from socket import gethostname
31
32
from string import Template
@@ -512,7 +513,7 @@ def write_graph(self, dotfilename='graph.dot', graph2use='hierarchical',
512
513
workflow nodes;
513
514
flat - expands workflow nodes recursively;
514
515
hierarchical - expands workflow nodes recursively with a
515
- notion on hierarchy;
516
+ notion on hierarchy;
516
517
colored - expands workflow nodes recursively with a
517
518
notion on hierarchy in color;
518
519
exec - expands workflows to depict iterables
@@ -529,17 +530,17 @@ def write_graph(self, dotfilename='graph.dot', graph2use='hierarchical',
529
530
if graph2use not in graphtypes :
530
531
raise ValueError ('Unknown graph2use keyword. Must be one of: ' +
531
532
str (graphtypes ))
532
- base_dir , dotfilename = os . path .split (dotfilename )
533
+ base_dir , dotfilename = op .split (dotfilename )
533
534
if base_dir == '' :
534
535
if self .base_dir :
535
536
base_dir = self .base_dir
536
537
if self .name :
537
- base_dir = os . path .join (base_dir , self .name )
538
+ base_dir = op .join (base_dir , self .name )
538
539
else :
539
540
base_dir = os .getcwd ()
540
541
base_dir = make_output_dir (base_dir )
541
542
if graph2use in ['hierarchical' , 'colored' ]:
542
- dotfilename = os . path .join (base_dir , dotfilename )
543
+ dotfilename = op .join (base_dir , dotfilename )
543
544
self .write_hierarchical_dotfile (dotfilename = dotfilename ,
544
545
colored = graph2use == "colored" ,
545
546
simple_form = simple_form )
@@ -697,7 +698,7 @@ def run(self, plugin=None, plugin_args=None, updatehash=False):
697
698
runner .run (execgraph , updatehash = updatehash , config = self .config )
698
699
datestr = datetime .utcnow ().strftime ('%Y%m%dT%H%M%S' )
699
700
if str2bool (self .config ['execution' ]['write_provenance' ]):
700
- prov_base = os . path .join (self .base_dir ,
701
+ prov_base = op .join (self .base_dir ,
701
702
'workflow_provenance_%s' % datestr )
702
703
logger .info ('Provenance file prefix: %s' % prov_base )
703
704
write_workflow_prov (execgraph , prov_base , format = 'all' )
@@ -708,17 +709,17 @@ def run(self, plugin=None, plugin_args=None, updatehash=False):
708
709
def _write_report_info (self , workingdir , name , graph ):
709
710
if workingdir is None :
710
711
workingdir = os .getcwd ()
711
- report_dir = os . path .join (workingdir , name )
712
- if not os . path .exists (report_dir ):
712
+ report_dir = op .join (workingdir , name )
713
+ if not op .exists (report_dir ):
713
714
os .makedirs (report_dir )
714
- shutil .copyfile (os . path . join (os . path .dirname (__file__ ),
715
+ shutil .copyfile (op . join (op .dirname (__file__ ),
715
716
'report_template.html' ),
716
- os . path .join (report_dir , 'index.html' ))
717
- shutil .copyfile (os . path . join (os . path .dirname (__file__ ),
717
+ op .join (report_dir , 'index.html' ))
718
+ shutil .copyfile (op . join (op .dirname (__file__ ),
718
719
'..' , 'external' , 'd3.v3.min.js' ),
719
- os . path .join (report_dir , 'd3.v3.min.js' ))
720
+ op .join (report_dir , 'd3.v3.min.js' ))
720
721
nodes , groups = topological_sort (graph , depth_first = True )
721
- graph_file = os . path .join (report_dir , 'graph1.json' )
722
+ graph_file = op .join (report_dir , 'graph1.json' )
722
723
json_dict = {'nodes' : [], 'links' : [], 'groups' : [], 'maxN' : 0 }
723
724
for i , node in enumerate (nodes ):
724
725
report_file = "%s/_report/report.rst" % \
@@ -745,7 +746,7 @@ def _write_report_info(self, workingdir, name, graph):
745
746
target = nodes .index (v ),
746
747
value = 1 ))
747
748
save_json (graph_file , json_dict )
748
- graph_file = os . path .join (report_dir , 'graph.json' )
749
+ graph_file = op .join (report_dir , 'graph.json' )
749
750
template = '%%0%dd_' % np .ceil (np .log10 (len (nodes ))).astype (int )
750
751
def getname (u , i ):
751
752
name_parts = u .fullname .split ('.' )
@@ -790,7 +791,7 @@ def _configure_exec_nodes(self, graph):
790
791
data = graph .get_edge_data (* edge )
791
792
for sourceinfo , field in sorted (data ['connect' ]):
792
793
node .input_source [field ] = \
793
- (os . path .join (edge [0 ].output_dir (),
794
+ (op .join (edge [0 ].output_dir (),
794
795
'result_%s.pklz' % edge [0 ].name ),
795
796
sourceinfo )
796
797
@@ -1245,15 +1246,15 @@ def output_dir(self):
1245
1246
self .base_dir = mkdtemp ()
1246
1247
outputdir = self .base_dir
1247
1248
if self ._hierarchy :
1248
- outputdir = os . path .join (outputdir , * self ._hierarchy .split ('.' ))
1249
+ outputdir = op .join (outputdir , * self ._hierarchy .split ('.' ))
1249
1250
if self .parameterization :
1250
1251
if not str2bool (self .config ['execution' ]['parameterize_dirs' ]):
1251
1252
param_dirs = [self ._parameterization_dir (p ) for p in
1252
1253
self .parameterization ]
1253
- outputdir = os . path .join (outputdir , * param_dirs )
1254
+ outputdir = op .join (outputdir , * param_dirs )
1254
1255
else :
1255
- outputdir = os . path .join (outputdir , * self .parameterization )
1256
- return os . path . abspath (os . path .join (outputdir ,
1256
+ outputdir = op .join (outputdir , * self .parameterization )
1257
+ return op . abspath (op .join (outputdir ,
1257
1258
self .name ))
1258
1259
1259
1260
def set_input (self , parameter , val ):
@@ -1284,23 +1285,23 @@ def hash_exists(self, updatehash=False):
1284
1285
# of the dictionary itself.
1285
1286
hashed_inputs , hashvalue = self ._get_hashval ()
1286
1287
outdir = self .output_dir ()
1287
- if os . path .exists (outdir ):
1288
+ if op .exists (outdir ):
1288
1289
logger .debug (os .listdir (outdir ))
1289
- hashfiles = glob (os . path .join (outdir , '_0x*.json' ))
1290
+ hashfiles = glob (op .join (outdir , '_0x*.json' ))
1290
1291
logger .debug (hashfiles )
1291
1292
if len (hashfiles ) > 1 :
1292
1293
logger .info (hashfiles )
1293
1294
logger .info ('Removing multiple hashfiles and forcing node to rerun' )
1294
1295
for hashfile in hashfiles :
1295
1296
os .unlink (hashfile )
1296
- hashfile = os . path .join (outdir , '_0x%s.json' % hashvalue )
1297
+ hashfile = op .join (outdir , '_0x%s.json' % hashvalue )
1297
1298
logger .debug (hashfile )
1298
- if updatehash and os . path .exists (outdir ):
1299
+ if updatehash and op .exists (outdir ):
1299
1300
logger .debug ("Updating hash: %s" % hashvalue )
1300
- for file in glob (os . path .join (outdir , '_0x*.json' )):
1301
+ for file in glob (op .join (outdir , '_0x*.json' )):
1301
1302
os .remove (file )
1302
1303
self ._save_hashfile (hashfile , hashed_inputs )
1303
- return os . path .exists (hashfile ), hashvalue , hashfile , hashed_inputs
1304
+ return op .exists (hashfile ), hashvalue , hashfile , hashed_inputs
1304
1305
1305
1306
def run (self , updatehash = False ):
1306
1307
"""Execute the node in its directory.
@@ -1321,7 +1322,7 @@ def run(self, updatehash=False):
1321
1322
self ._got_inputs = True
1322
1323
outdir = self .output_dir ()
1323
1324
logger .info ("Executing node %s in dir: %s" % (self ._id , outdir ))
1324
- if os . path .exists (outdir ):
1325
+ if op .exists (outdir ):
1325
1326
logger .debug (os .listdir (outdir ))
1326
1327
hash_info = self .hash_exists (updatehash = updatehash )
1327
1328
hash_exists , hashvalue , hashfile , hashed_inputs = hash_info
@@ -1337,7 +1338,7 @@ def run(self, updatehash=False):
1337
1338
# by rerunning we mean only nodes that did finish to run previously
1338
1339
json_pat = op .join (outdir , '_0x*.json' )
1339
1340
json_unfinished_pat = op .join (outdir , '_0x*_unfinished.json' )
1340
- need_rerun = (os . path .exists (outdir )
1341
+ need_rerun = (op .exists (outdir )
1341
1342
and not isinstance (self , MapNode )
1342
1343
and len (glob (json_pat )) != 0
1343
1344
and len (glob (json_unfinished_pat )) == 0 )
@@ -1352,7 +1353,7 @@ def run(self, updatehash=False):
1352
1353
str (self .overwrite ),
1353
1354
str (self ._interface .always_run ),
1354
1355
hashfile ,
1355
- str (os . path .exists (hashfile )),
1356
+ str (op .exists (hashfile )),
1356
1357
self .config ['execution' ]['hash_method' ].lower ()))
1357
1358
log_debug = config .get ('logging' , 'workflow_level' ) == 'DEBUG'
1358
1359
if log_debug and not op .exists (hashfile ):
@@ -1376,7 +1377,7 @@ def run(self, updatehash=False):
1376
1377
if cannot_rerun :
1377
1378
raise Exception (("Cannot rerun when 'stop_on_first_rerun' "
1378
1379
"is set to True" ))
1379
- hashfile_unfinished = os . path .join (outdir ,
1380
+ hashfile_unfinished = op .join (outdir ,
1380
1381
'_0x%s_unfinished.json' %
1381
1382
hashvalue )
1382
1383
if op .exists (hashfile ):
@@ -1387,20 +1388,35 @@ def run(self, updatehash=False):
1387
1388
and not isinstance (self , MapNode ))
1388
1389
if rm_outdir :
1389
1390
logger .debug ("Removing old %s and its contents" % outdir )
1390
- rmtree (outdir )
1391
+ try :
1392
+ rmtree (outdir )
1393
+ except OSError as ex :
1394
+ outdircont = os .listdir (outdir )
1395
+ if ((ex .errno == errno .ENOTEMPTY ) and (len (outdircont ) == 0 )):
1396
+ logger .warn (('An exception was raised trying to remove old %s, '
1397
+ 'but the path seems empty. Is it an NFS mount?. '
1398
+ 'Passing the exception.' ) % outdir )
1399
+ pass
1400
+ elif ((ex .errno == errno .ENOTEMPTY ) and (len (outdircont ) != 0 )):
1401
+ logger .debug (('Folder contents (%d items): '
1402
+ '%s' ) % (len (outdircont ), outdircont ))
1403
+ raise ex
1404
+ else :
1405
+ raise ex
1406
+
1391
1407
else :
1392
1408
logger .debug (("%s found and can_resume is True or Node is a "
1393
1409
"MapNode - resuming execution" ) %
1394
1410
hashfile_unfinished )
1395
1411
if isinstance (self , MapNode ):
1396
1412
# remove old json files
1397
- for filename in glob (os . path .join (outdir , '_0x*.json' )):
1413
+ for filename in glob (op .join (outdir , '_0x*.json' )):
1398
1414
os .unlink (filename )
1399
1415
outdir = make_output_dir (outdir )
1400
1416
self ._save_hashfile (hashfile_unfinished , hashed_inputs )
1401
1417
self .write_report (report_type = 'preexec' , cwd = outdir )
1402
- savepkl (os . path .join (outdir , '_node.pklz' ), self )
1403
- savepkl (os . path .join (outdir , '_inputs.pklz' ),
1418
+ savepkl (op .join (outdir , '_node.pklz' ), self )
1419
+ savepkl (op .join (outdir , '_inputs.pklz' ),
1404
1420
self .inputs .get_traitsfree ())
1405
1421
try :
1406
1422
self ._run_interface ()
@@ -1410,13 +1426,13 @@ def run(self, updatehash=False):
1410
1426
shutil .move (hashfile_unfinished , hashfile )
1411
1427
self .write_report (report_type = 'postexec' , cwd = outdir )
1412
1428
else :
1413
- if not os . path . exists (os . path .join (outdir , '_inputs.pklz' )):
1429
+ if not op . exists (op .join (outdir , '_inputs.pklz' )):
1414
1430
logger .debug ('%s: creating inputs file' % self .name )
1415
- savepkl (os . path .join (outdir , '_inputs.pklz' ),
1431
+ savepkl (op .join (outdir , '_inputs.pklz' ),
1416
1432
self .inputs .get_traitsfree ())
1417
- if not os . path . exists (os . path .join (outdir , '_node.pklz' )):
1433
+ if not op . exists (op .join (outdir , '_node.pklz' )):
1418
1434
logger .debug ('%s: creating node file' % self .name )
1419
- savepkl (os . path .join (outdir , '_node.pklz' ), self )
1435
+ savepkl (op .join (outdir , '_node.pklz' ), self )
1420
1436
logger .debug ("Hashfile exists. Skipping execution" )
1421
1437
self ._run_interface (execute = False , updatehash = updatehash )
1422
1438
logger .debug ('Finished running %s in dir: %s\n ' % (self ._id , outdir ))
@@ -1517,7 +1533,7 @@ def _run_interface(self, execute=True, updatehash=False):
1517
1533
os .chdir (old_cwd )
1518
1534
1519
1535
def _save_results (self , result , cwd ):
1520
- resultsfile = os . path .join (cwd , 'result_%s.pklz' % self .name )
1536
+ resultsfile = op .join (cwd , 'result_%s.pklz' % self .name )
1521
1537
if result .outputs :
1522
1538
try :
1523
1539
outputs = result .outputs .get ()
@@ -1550,10 +1566,10 @@ def _load_resultfile(self, cwd):
1550
1566
rerun
1551
1567
"""
1552
1568
aggregate = True
1553
- resultsoutputfile = os . path .join (cwd , 'result_%s.pklz' % self .name )
1569
+ resultsoutputfile = op .join (cwd , 'result_%s.pklz' % self .name )
1554
1570
result = None
1555
1571
attribute_error = False
1556
- if os . path .exists (resultsoutputfile ):
1572
+ if op .exists (resultsoutputfile ):
1557
1573
pkl_file = gzip .open (resultsoutputfile , 'rb' )
1558
1574
try :
1559
1575
result = cPickle .load (pkl_file )
@@ -1589,7 +1605,7 @@ def _load_results(self, cwd):
1589
1605
if aggregate :
1590
1606
logger .debug ('aggregating results' )
1591
1607
if attribute_error :
1592
- old_inputs = loadpkl (os . path .join (cwd , '_inputs.pklz' ))
1608
+ old_inputs = loadpkl (op .join (cwd , '_inputs.pklz' ))
1593
1609
self .inputs .set (** old_inputs )
1594
1610
if not isinstance (self , MapNode ):
1595
1611
self ._copyfiles_to_wd (cwd , True , linksonly = True )
@@ -1633,7 +1649,7 @@ def _run_command(self, execute, copyfiles=True):
1633
1649
except Exception , msg :
1634
1650
self ._result .runtime .stderr = msg
1635
1651
raise
1636
- cmdfile = os . path .join (cwd , 'command.txt' )
1652
+ cmdfile = op .join (cwd , 'command.txt' )
1637
1653
fd = open (cmdfile , 'wt' )
1638
1654
fd .writelines (cmd + "\n " )
1639
1655
fd .close ()
@@ -1646,7 +1662,7 @@ def _run_command(self, execute, copyfiles=True):
1646
1662
1647
1663
dirs2keep = None
1648
1664
if isinstance (self , MapNode ):
1649
- dirs2keep = [os . path .join (cwd , 'mapflow' )]
1665
+ dirs2keep = [op .join (cwd , 'mapflow' )]
1650
1666
result .outputs = clean_working_directory (result .outputs , cwd ,
1651
1667
self ._interface .inputs ,
1652
1668
self .needed_outputs ,
@@ -1670,7 +1686,7 @@ def _strip_temp(self, files, wd):
1670
1686
if isinstance (f , list ):
1671
1687
out .append (self ._strip_temp (f , wd ))
1672
1688
else :
1673
- out .append (f .replace (os . path .join (wd , '_tempinput' ), wd ))
1689
+ out .append (f .replace (op .join (wd , '_tempinput' ), wd ))
1674
1690
return out
1675
1691
1676
1692
def _copyfiles_to_wd (self , outdir , execute , linksonly = False ):
@@ -1680,7 +1696,7 @@ def _copyfiles_to_wd(self, outdir, execute, linksonly=False):
1680
1696
(str (execute ), str (linksonly )))
1681
1697
if execute and linksonly :
1682
1698
olddir = outdir
1683
- outdir = os . path .join (outdir , '_tempinput' )
1699
+ outdir = op .join (outdir , '_tempinput' )
1684
1700
os .makedirs (outdir )
1685
1701
for info in self ._interface ._get_filecopy_info ():
1686
1702
files = self .inputs .get ().get (info ['key' ])
@@ -1700,7 +1716,7 @@ def _copyfiles_to_wd(self, outdir, execute, linksonly=False):
1700
1716
newpath = outdir )
1701
1717
newfiles = self ._strip_temp (
1702
1718
newfiles ,
1703
- op .abspath (olddir ).split (os . path .sep )[- 1 ])
1719
+ op .abspath (olddir ).split (op .sep )[- 1 ])
1704
1720
else :
1705
1721
newfiles = copyfiles (infiles ,
1706
1722
[outdir ],
@@ -1720,9 +1736,9 @@ def update(self, **opts):
1720
1736
def write_report (self , report_type = None , cwd = None ):
1721
1737
if not str2bool (self .config ['execution' ]['create_report' ]):
1722
1738
return
1723
- report_dir = os . path .join (cwd , '_report' )
1724
- report_file = os . path .join (report_dir , 'report.rst' )
1725
- if not os . path .exists (report_dir ):
1739
+ report_dir = op .join (cwd , '_report' )
1740
+ report_file = op .join (report_dir , 'report.rst' )
1741
+ if not op .exists (report_dir ):
1726
1742
os .makedirs (report_dir )
1727
1743
if report_type == 'preexec' :
1728
1744
logger .debug ('writing pre-exec report to %s' % report_file )
@@ -2038,7 +2054,6 @@ def __init__(self, interface, iterfield, name, serial=False, **kwargs):
2038
2054
fields = self .iterfield )
2039
2055
self ._inputs .on_trait_change (self ._set_mapnode_input )
2040
2056
self ._got_inputs = False
2041
-
2042
2057
self ._serial = serial
2043
2058
2044
2059
def _create_dynamic_traits (self , basetraits , fields = None , nitems = None ):
@@ -2137,7 +2152,7 @@ def _make_nodes(self, cwd=None):
2137
2152
setattr (node .inputs , field ,
2138
2153
fieldvals [i ])
2139
2154
node .config = self .config
2140
- node .base_dir = os . path .join (cwd , 'mapflow' )
2155
+ node .base_dir = op .join (cwd , 'mapflow' )
2141
2156
yield i , node
2142
2157
2143
2158
def _node_runner (self , nodes , updatehash = False ):
@@ -2199,8 +2214,8 @@ def write_report(self, report_type=None, cwd=None):
2199
2214
super (MapNode , self ).write_report (report_type = report_type , cwd = cwd )
2200
2215
if report_type == 'postexec' :
2201
2216
super (MapNode , self ).write_report (report_type = report_type , cwd = cwd )
2202
- report_dir = os . path .join (cwd , '_report' )
2203
- report_file = os . path .join (report_dir , 'report.rst' )
2217
+ report_dir = op .join (cwd , '_report' )
2218
+ report_file = op .join (report_dir , 'report.rst' )
2204
2219
fp = open (report_file , 'at' )
2205
2220
fp .writelines (write_rst_header ('Subnode reports' , level = 1 ))
2206
2221
nitems = len (filename_to_list (
@@ -2209,7 +2224,7 @@ def write_report(self, report_type=None, cwd=None):
2209
2224
for i in range (nitems ):
2210
2225
nodename = '_' + self .name + str (i )
2211
2226
subnode_report_files .insert (i , 'subnode %d' % i + ' : ' +
2212
- os . path .join (cwd ,
2227
+ op .join (cwd ,
2213
2228
'mapflow' ,
2214
2229
nodename ,
2215
2230
'_report' ,
@@ -2282,9 +2297,9 @@ def _run_interface(self, execute=True, updatehash=False):
2282
2297
self ._save_results (self ._result , cwd )
2283
2298
# remove any node directories no longer required
2284
2299
dirs2remove = []
2285
- for path in glob (os . path .join (cwd , 'mapflow' , '*' )):
2286
- if os . path .isdir (path ):
2287
- if path .split (os . path .sep )[- 1 ] not in nodenames :
2300
+ for path in glob (op .join (cwd , 'mapflow' , '*' )):
2301
+ if op .isdir (path ):
2302
+ if path .split (op .sep )[- 1 ] not in nodenames :
2288
2303
dirs2remove .append (path )
2289
2304
for path in dirs2remove :
2290
2305
shutil .rmtree (path )
0 commit comments