import os
import sys
import json
import traceback
from deriva.transfer import DerivaUpload, DerivaUploadError, DerivaUploadConfigurationError, \
DerivaUploadCatalogCreateError, DerivaUploadCatalogUpdateError
from deriva.core import BaseCLI, write_config, format_credential, format_exception, urlparse
[docs]class DerivaUploadCLI(BaseCLI):
def __init__(self, uploader, description, epilog):
if not issubclass(uploader, DerivaUpload):
raise TypeError("DerivaUpload subclass required")
BaseCLI.__init__(self, description, epilog, uploader.getVersion(), hostname_required=True)
self.parser.add_argument('--no-config-update', action="store_true",
help="Do not check for (and download) an updated configuration from the server.")
self.parser.add_argument('--purge-state', action="store_true",
help="Purge (delete) any existing transfer state files found in the directory "
"hierarchy of the input path.")
self.parser.add_argument('--dry-run', action="store_true",
help="Scan the input directory for matching files to upload, "
"but do not transfer any files.")
self.parser.add_argument('--output-file', metavar='<file>',
help="Optional path where a JSON-formatted output file will be written, "
"containing file upload status and associated metadata.")
self.parser.add_argument("--catalog", default=1, metavar="<1>", help="Catalog number. Default: 1")
self.parser.add_argument("path", metavar="<input dir>", help="Path to an input directory.")
self.uploader = uploader
[docs] @staticmethod
def upload(uploader,
data_path,
hostname,
catalog=1,
token=None,
config_file=None,
credential_file=None,
no_update=False,
purge=False,
dry_run=False,
output_file=None):
if not issubclass(uploader, DerivaUpload):
raise TypeError("DerivaUpload subclass required")
assert hostname
server = dict()
server["catalog_id"] = catalog
if hostname.startswith("http"):
url = urlparse(hostname)
server["protocol"] = url.scheme
server["host"] = url.netloc
else:
server["protocol"] = "https"
server["host"] = hostname
deriva_uploader = uploader(config_file, credential_file, server, dcctx_cid="cli/" + DerivaUploadCLI.__name__)
if token:
deriva_uploader.setCredentials(format_credential(token))
if not config_file and not no_update:
config = deriva_uploader.getUpdatedConfig()
if config:
write_config(deriva_uploader.getDeployedConfigFilePath(), config)
if not deriva_uploader.isVersionCompatible():
raise RuntimeError("Version incompatibility detected", "Current version: [%s], required version(s): %s." % (
deriva_uploader.getVersion(), deriva_uploader.getVersionCompatibility()))
deriva_uploader.scanDirectory(data_path, abort_on_invalid_input=False, purge_state=purge)
if not dry_run:
results = deriva_uploader.uploadFiles()
if output_file:
with open(output_file, "w") as output:
json.dump(results, output)
deriva_uploader.cleanup()
[docs] def main(self):
args = self.parse_cli()
if args.path is None:
sys.stderr.write("\nError: Input directory not specified.\n")
self.parser.print_usage()
return 2
if not args.quiet:
sys.stderr.write("\n")
try:
DerivaUploadCLI.upload(self.uploader,
os.path.abspath(args.path),
args.host,
args.catalog,
args.token,
args.config_file,
args.credential_file,
args.no_config_update,
args.purge_state,
args.dry_run,
args.output_file)
except (RuntimeError, FileNotFoundError, DerivaUploadError, DerivaUploadConfigurationError,
DerivaUploadCatalogCreateError, DerivaUploadCatalogUpdateError) as e:
sys.stderr.write(("\n" if not args.quiet else "") + format_exception(e))
if args.debug:
traceback.print_exc()
return 1
except:
traceback.print_exc()
return 1
finally:
if not args.quiet:
sys.stderr.write("\n\n")
return 0