Source code for COMPS.utils.get_output_files_for_workitem
import os
import logging
from COMPS import Client
from COMPS.Data import WorkItem
logger = logging.getLogger(__name__)
##########################
utility_metadata = {
'aliases': [ 'getwiout' ],
'help': 'Download output files from a workitem',
'description': 'This utility downloads one or more output files from a workitem. By ' +
'default, files are written relative to the current directory, in the hierarchy:' + os.linesep +
' ./<workitem-id>/<filename>' + os.linesep +
'but if calling from script, a custom function can be provided to control location and ' +
'name of the files written.',
'epilog': '''examples:
%(prog)s 11111111-2222-3333-4444-000000000000 schema.json
%(prog)s 11111111-2222-3333-4444-000000000000 stdout.txt,stderr.txt
'''
}
[docs]def fill_parser(p):
p.add_argument('workitem_id', help='Id of the workitem to download files from')
p.add_argument('filename', help='Name(s) of the file(s) to download from the workitem. This can be a comma-delimited list, or an actual (python) list if calling from code')
p.add_argument('--overwrite', '-ow', action='store_true', help='Overwrite local files if they already exist (default is to skip if a local file with the same subdir/name exists)')
p.add_argument('--casesensitive', '-cs', action='store_true', help='Make filename comparisons case-sensitive (default is case-insensitive, i.e. ignoring case)')
##########################
# The default path builder
[docs]def path_builder_simple(wi, filename):
return os.path.join(str(wi.id), filename)
##########################
[docs]def get_files( workitem_id, files_to_get, overwrite=False, casesensitive=False, output_path_builder=path_builder_simple ):
if not isinstance(files_to_get, list):
files_to_get = [ files_to_get ]
files_to_get_int = files_to_get if casesensitive else [ f.lower() for f in files_to_get ]
wi = WorkItem.get(workitem_id)
logger.info(f'Found workitem {wi.id}')
hit_fileexists = False
wo = wi.retrieve_output_file_info(None)
logger.debug(f'wi {wi.id} - {len(wo)} output files found')
found_file_num = 0
for ofmd in wo:
fn_comp = ofmd.friendly_name if casesensitive else ofmd.friendly_name.lower()
if fn_comp in files_to_get_int:
found_file_num += 1
filepath = output_path_builder(wi, ofmd.friendly_name)
pn = os.path.dirname(filepath)
if not os.path.exists(pn):
os.makedirs(pn, exist_ok=True)
logger.info(filepath)
oba = wi.retrieve_output_files_from_info([ofmd])
try:
with open(filepath, 'wb' if overwrite else 'xb') as outfile:
outfile.write(oba[0])
except FileExistsError as e:
logger.error(f'Output file already exists at {filepath}. Skipping...')
logger.debug(e, exc_info=True)
hit_fileexists = True
# if we didn't find enough matching files, spit out a message
if found_file_num < len(files_to_get_int):
logger.warning(f'Couldn\'t find all files matching request (possible typo, casing issue, or requested an input-asset?)')
if hit_fileexists:
logger.warning('Skipped downloading of some files because they already exist locally. Rerun using \'--overwrite\' if you want these overwritten instead')
[docs]def main(args):
Client.login(args.comps_server)
get_files(args.workitem_id, args.filename.split(','), args.overwrite, args.casesensitive)