def add(self, input_name, input_value): if self.input_name_prefix is not None: if input_name.startswith(self.input_name_prefix): input_name = input_name[len(self.input_name_prefix):] else: # Skip inputs that don't start with prefix return if ':' in input_name: input_class = input_name[input_name.find(':') + 1:] input_name = input_name[:input_name.find(':')] else: input_class = None if self.input_spec is not None: if input_name not in self.input_spec: raise Exception('Input field called ' + input_name + ' was not found in the input spec') input_class = self.input_spec[input_name]['class'] if input_class is None: done = False try: # Resolve "job-xxxx:output-name" syntax into a canonical job ref job_id, field = split_unescaped(':', input_value) if is_job_id(job_id) or is_localjob_id(job_id): input_value = {"job": job_id, "field": field} done = True except: pass if not done: try: parsed_input_value = json.loads(input_value, object_pairs_hook=collections.OrderedDict) if type(parsed_input_value) in (collections.OrderedDict, list, int, long, float): input_value = parsed_input_value else: raise Exception() except: # Not recognized JSON (list or dict), so resolve it as a name try: project, folderpath, entity_result = resolve_existing_path(input_value, expected='entity') except: # If not possible, then leave it as a string project, folderpath, entity_result = None, None, None if entity_result is not None: if is_hashid(input_value): input_value = {'$dnanexus_link': entity_result['id']} else: input_value = {"$dnanexus_link": {"project": entity_result['describe']['project'], "id": entity_result['id']}} self.inputs[input_name].append(input_value) else: # Input class is known. Respect the "array" class. input_value = parse_input_or_jbor(input_class, input_value) if input_class.startswith('array:'): self.inputs[input_name].append(input_value) else: self.inputs[input_name] = input_value
def parse_input_or_jbor(in_class, value): val_substrings = split_unescaped(':', value) if len(val_substrings) == 2 and (is_job_id(val_substrings[0]) or is_localjob_id(val_substrings[0])): return {"job": val_substrings[0], "field": val_substrings[1]} else: if in_class.startswith('array:'): in_class = in_class[6:] return parse_input[in_class](value)
def update_from_args(self, args): if args.filename is not None: try: if args.filename == "-": data = sys.stdin.read() else: with open(args.filename, 'r') as fd: data = fd.read() self.update( json.loads(data, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise Exception('Error while parsing input JSON file: %s' % unicode(e)) if args.input_json is not None: try: self.update( json.loads(args.input_json, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise Exception('Error while parsing input JSON: %s' % unicode(e)) if args.input is not None: for keyeqval in args.input: try: first_eq_pos = get_first_pos_of_char('=', keyeqval) if first_eq_pos == -1: raise name = split_unescaped('=', keyeqval)[0] value = keyeqval[first_eq_pos + 1:] except: raise Exception( 'An input was found that did not conform to the syntax: -i<input name>=<input value>' ) self.add(self.executable._get_input_name(name) if \ self._desc.get('class') == 'workflow' else name, value) if self.input_spec is None: for i in self.inputs: if type(self.inputs[i]) == list and len(self.inputs[i]) == 1: self.inputs[i] = self.inputs[i][0] # For now, we do not handle prompting for workflow inputs nor # recognizing when not all inputs haven't been bound if sys.stdout.isatty() and self._desc.get('class') != 'workflow': self.prompt_for_missing() elif self._desc.get('class') != 'workflow': missing_required_inputs = set(self.required_inputs) - set( self.inputs.keys()) if missing_required_inputs: raise Exception( 'Some inputs (%s) are missing, and interactive mode is not available' % (', '.join(missing_required_inputs)))
def get_matches(self, line, point, prefix, suffix): # This implementation is reliant on bash behavior that ':' is # treated as a word separator for determining prefix if get_last_pos_of_char(' ', line) != point - 1: prefix = split_unescaped(' ', line[:point])[-1] self._populate_matches(prefix) if prefix.rfind(':') != -1: for i in range(len(self.matches)): self.matches[i] = self.matches[i][self.matches[i].rfind(':') + 1:] return self.matches
def get_matches(self, line, point, prefix, suffix): # This implementation is reliant on bash behavior that ':' is # treated as a word separator for determining prefix if get_last_pos_of_char(' ', line) != point - 1: prefix = split_unescaped(' ', line[:point])[-1] # Can immediately return if there are disallowed characters of # app names in the prefix if ':' in prefix: return [] self._populate_matches(prefix) return self.matches
def process_properties_args(args): # Properties properties = None if args.properties is not None: properties = {} for keyeqval in args.properties: try: key, val = split_unescaped('=', keyeqval) except: raise DXParserError('Property key-value pair must be given using syntax "property_key=property_value"') properties[key] = val args.properties = properties
def update_from_args(self, args, require_all_inputs=True): if args.filename is not None: try: if args.filename == "-": data = sys.stdin.read() else: with open(args.filename, 'r') as fd: data = fd.read() self.update(json.loads(data, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise DXCLIError('Error while parsing input JSON file: %s' % unicode(e)) if args.input_json is not None: try: self.update(json.loads(args.input_json, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise DXCLIError('Error while parsing input JSON: %s' % unicode(e)) if args.input is not None: for keyeqval in args.input: try: first_eq_pos = get_first_pos_of_char('=', keyeqval) if first_eq_pos == -1: raise name = split_unescaped('=', keyeqval)[0] value = keyeqval[first_eq_pos + 1:] except: raise DXCLIError('An input was found that did not conform to the syntax: -i<input name>=<input value>') self.add(self.executable._get_input_name(name) if \ self._desc.get('class') == 'workflow' else name, value) if self.input_spec is None: for i in self.inputs: if type(self.inputs[i]) == list and len(self.inputs[i]) == 1: self.inputs[i] = self.inputs[i][0] # For now, we do not handle prompting for workflow inputs nor # recognizing when not all inputs haven't been bound if require_all_inputs: if sys.stdout.isatty() and self._desc.get('class') != 'workflow': self.prompt_for_missing() elif self._desc.get('class') != 'workflow': missing_required_inputs = set(self.required_inputs) - set(self.inputs.keys()) if missing_required_inputs: raise DXCLIError('Some inputs (%s) are missing, and interactive mode is not available' % (', '.join(missing_required_inputs)))
def update_from_args(self, args): if args.filename is not None: try: if args.filename == "-": data = sys.stdin.read() else: with open(args.filename, 'r') as fd: data = fd.read() self.update(json.loads(data, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise Exception('Error while parsing input JSON file: %s' % unicode(e)) if args.input_json is not None: try: self.update(json.loads(args.input_json, object_pairs_hook=collections.OrderedDict)) except Exception as e: raise Exception('Error while parsing input JSON: %s' % unicode(e)) if args.input is not None: for keyeqval in args.input: try: first_eq_pos = get_first_pos_of_char('=', keyeqval) if first_eq_pos == -1: raise name = split_unescaped('=', keyeqval)[0] value = keyeqval[first_eq_pos + 1:] except: raise Exception('An input was found that did not conform to the syntax: -i<input name>=<input value>') self.add(name, value) if self.input_spec is None: for i in self.inputs: if type(self.inputs[i]) == list and len(self.inputs[i]) == 1: self.inputs[i] = self.inputs[i][0] if sys.stdout.isatty(): self.prompt_for_missing() else: missing_required_inputs = set(self.required_inputs) - set(self.inputs.keys()) if missing_required_inputs: raise Exception('Some inputs (%s) are missing, and interactive mode is not available' % (', '.join(missing_required_inputs)))
def add(self, input_name, input_value): if self.input_name_prefix is not None: if input_name.startswith(self.input_name_prefix): input_name = input_name[len(self.input_name_prefix):] else: # Skip inputs that don't start with prefix return if ':' in input_name: input_class = input_name[input_name.find(':') + 1:] input_name = input_name[:input_name.find(':')] else: input_class = None if self.input_spec is not None: if input_name not in self.input_spec and self._desc.get( 'class') != 'workflow': raise Exception('Input field called ' + input_name + ' was not found in the input spec') elif input_name in self.input_spec: input_class = self.input_spec[input_name]['class'] if input_class is None: done = False try: # Resolve "job-xxxx:output-name" syntax into a canonical job ref job_id, field = split_unescaped(':', input_value) if is_job_id(job_id) or is_localjob_id(job_id): input_value = {"job": job_id, "field": field} done = True except: pass if not done: try: parsed_input_value = json.loads( input_value, object_pairs_hook=collections.OrderedDict) if type(parsed_input_value) in (collections.OrderedDict, list, int, long, float): input_value = parsed_input_value else: raise Exception() except: # Not recognized JSON (list or dict), so resolve it as a name try: project, folderpath, entity_result = resolve_existing_path( input_value, expected='entity') except: # If not possible, then leave it as a string project, folderpath, entity_result = None, None, None if entity_result is not None: if is_hashid(input_value): input_value = { '$dnanexus_link': entity_result['id'] } else: input_value = { "$dnanexus_link": { "project": entity_result['describe']['project'], "id": entity_result['id'] } } if isinstance(self.inputs[input_name], list) and \ not isinstance(self.inputs[input_name], basestring): self.inputs[input_name].append(input_value) else: self.inputs[input_name] = input_value else: # Input class is known. Respect the "array" class. input_value = parse_input_or_jbor(input_class, input_value) if input_class.startswith('array:'): self.inputs[input_name].append(input_value) else: self.inputs[input_name] = input_value