|
25 | 25 |
|
26 | 26 | from ... import logging, config, LooseVersion
|
27 | 27 | from ...utils.filemanip import (
|
| 28 | + indirectory, |
28 | 29 | relpath,
|
29 | 30 | makedirs,
|
30 | 31 | fname_presuffix,
|
|
40 | 41 | )
|
41 | 42 | from ...utils.misc import str2bool
|
42 | 43 | from ...utils.functions import create_function_from_source
|
| 44 | +from ...interfaces.base.traits_extension import rebase_path_traits, resolve_path_traits |
43 | 45 | from ...interfaces.base import (Bunch, CommandLine, isdefined, Undefined,
|
44 | 46 | InterfaceResult, traits)
|
45 | 47 | from ...interfaces.utility import IdentityInterface
|
@@ -284,86 +286,88 @@ def _protect_collapses(hastraits):
|
284 | 286 | return _uncollapse(hastraits.trait_get(), collapsed)
|
285 | 287 |
|
286 | 288 |
|
287 |
| -def save_resultfile(result, cwd, name): |
288 |
| - """Save a result pklz file to ``cwd``""" |
| 289 | +def save_resultfile(result, cwd, name, rebase=True): |
| 290 | + """Save a result pklz file to ``cwd``.""" |
| 291 | + cwd = os.path.abspath(cwd) |
289 | 292 | resultsfile = os.path.join(cwd, 'result_%s.pklz' % name)
|
290 |
| - if result.outputs: |
291 |
| - try: |
292 |
| - collapsed = _identify_collapses(result.outputs) |
293 |
| - outputs = _uncollapse(result.outputs.trait_get(), collapsed) |
294 |
| - # Double-protect tosave so that the original, uncollapsed trait |
295 |
| - # is saved in the pickle file. Thus, when the loading process |
296 |
| - # collapses, the original correct value is loaded. |
297 |
| - tosave = _uncollapse(outputs.copy(), collapsed) |
298 |
| - except AttributeError: |
299 |
| - tosave = outputs = result.outputs.dictcopy() # outputs was a bunch |
300 |
| - for k, v in list(modify_paths(tosave, relative=True, basedir=cwd).items()): |
301 |
| - setattr(result.outputs, k, v) |
302 |
| - |
303 |
| - savepkl(resultsfile, result) |
304 |
| - logger.debug('saved results in %s', resultsfile) |
305 |
| - |
306 |
| - if result.outputs: |
307 |
| - for k, v in list(outputs.items()): |
308 |
| - setattr(result.outputs, k, v) |
309 |
| - |
310 |
| - |
311 |
| -def load_resultfile(path, name): |
| 293 | + logger.debug("Saving results file: '%s'", resultsfile) |
| 294 | + |
| 295 | + if result.outputs is None: |
| 296 | + logger.warn('Storing result file without outputs') |
| 297 | + savepkl(resultsfile, result) |
| 298 | + return |
| 299 | + |
| 300 | + try: |
| 301 | + outputs = result.outputs.trait_get() |
| 302 | + except AttributeError: |
| 303 | + logger.debug('Storing non-traited results, skipping rebase of paths') |
| 304 | + savepkl(resultsfile, result) |
| 305 | + return |
| 306 | + |
| 307 | + try: |
| 308 | + with indirectory(cwd): |
| 309 | + # All the magic to fix #2944 resides here: |
| 310 | + for key, val in list(outputs.items()): |
| 311 | + val = rebase_path_traits(result.outputs.trait(key), val, cwd) |
| 312 | + setattr(result.outputs, key, val) |
| 313 | + savepkl(resultsfile, result) |
| 314 | + finally: |
| 315 | + # Reset resolved paths from the outputs dict no matter what |
| 316 | + for key, val in list(outputs.items()): |
| 317 | + setattr(result.outputs, key, val) |
| 318 | + |
| 319 | + |
| 320 | +def load_resultfile(path, name, resolve=True): |
312 | 321 | """
|
313 |
| - Load InterfaceResult file from path |
| 322 | + Load InterfaceResult file from path. |
314 | 323 |
|
315 | 324 | Parameter
|
316 | 325 | ---------
|
317 |
| -
|
318 | 326 | path : base_dir of node
|
319 | 327 | name : name of node
|
320 | 328 |
|
321 | 329 | Returns
|
322 | 330 | -------
|
323 |
| -
|
324 | 331 | result : InterfaceResult structure
|
325 | 332 | aggregate : boolean indicating whether node should aggregate_outputs
|
326 | 333 | attribute error : boolean indicating whether there was some mismatch in
|
327 | 334 | versions of traits used to store result and hence node needs to
|
328 | 335 | rerun
|
| 336 | +
|
329 | 337 | """
|
330 | 338 | aggregate = True
|
331 |
| - resultsoutputfile = os.path.join(path, 'result_%s.pklz' % name) |
332 | 339 | result = None
|
333 | 340 | attribute_error = False
|
334 |
| - if os.path.exists(resultsoutputfile): |
335 |
| - pkl_file = gzip.open(resultsoutputfile, 'rb') |
| 341 | + resultsoutputfile = os.path.join(path, 'result_%s.pklz' % name) |
| 342 | + if not os.path.exists(resultsoutputfile): |
| 343 | + return result, aggregate, attribute_error |
| 344 | + |
| 345 | + with indirectory(path): |
| 346 | + pkl_file = gzip.open('result_%s.pklz' % name, 'rb') |
336 | 347 | try:
|
337 | 348 | result = pickle.load(pkl_file)
|
338 | 349 | except UnicodeDecodeError:
|
339 | 350 | # Was this pickle created with Python 2.x?
|
340 |
| - pickle.load(pkl_file, fix_imports=True, encoding='utf-8') |
341 |
| - logger.warning('Successfully loaded pkl in compatibility mode') |
342 |
| - except (traits.TraitError, AttributeError, ImportError, |
343 |
| - EOFError) as err: |
344 |
| - if isinstance(err, (AttributeError, ImportError)): |
345 |
| - attribute_error = True |
346 |
| - logger.debug('attribute error: %s probably using ' |
347 |
| - 'different trait pickled file', str(err)) |
348 |
| - else: |
349 |
| - logger.debug( |
350 |
| - 'some file does not exist. hence trait cannot be set') |
| 351 | + result = pickle.load(pkl_file, fix_imports=True, encoding='utf-8') |
| 352 | + logger.warning('Successfully loaded pkl in compatibility mode.') |
| 353 | + except (traits.TraitError, EOFError): |
| 354 | + logger.debug( |
| 355 | + 'some file does not exist. hence trait cannot be set') |
| 356 | + except (AttributeError, ImportError) as err: |
| 357 | + attribute_error = True |
| 358 | + logger.debug('attribute error: %s probably using ' |
| 359 | + 'different trait pickled file', str(err)) |
351 | 360 | else:
|
352 |
| - if result.outputs: |
353 |
| - try: |
354 |
| - outputs = _protect_collapses(result.outputs) |
355 |
| - except AttributeError: |
356 |
| - outputs = result.outputs.dictcopy() # outputs == Bunch |
357 |
| - try: |
358 |
| - for k, v in list(modify_paths(outputs, relative=False, |
359 |
| - basedir=path).items()): |
360 |
| - setattr(result.outputs, k, v) |
361 |
| - except FileNotFoundError: |
362 |
| - logger.debug('conversion to full path results in ' |
363 |
| - 'non existent file') |
364 | 361 | aggregate = False
|
365 |
| - pkl_file.close() |
366 |
| - logger.debug('Aggregate: %s', aggregate) |
| 362 | + finally: |
| 363 | + pkl_file.close() |
| 364 | + |
| 365 | + if resolve and not aggregate: |
| 366 | + logger.debug('Resolving paths in outputs loaded from results file.') |
| 367 | + for trait_name, old_value in list(result.outputs.get().items()): |
| 368 | + value = resolve_path_traits(result.outputs.trait(trait_name), old_value, path) |
| 369 | + setattr(result.outputs, trait_name, value) |
| 370 | + |
367 | 371 | return result, aggregate, attribute_error
|
368 | 372 |
|
369 | 373 |
|
|
0 commit comments