def parse_destination(dest_str): """ Parses dest_str, which is (roughly) of the form PROJECT:/FOLDER/NAME, and returns a tuple (project, folder, name) """ # Interpret strings of form "project-XXXX" (no colon) as project. If # we pass these through to resolve_path they would get interpreted # as folder names... if is_container_id(dest_str): return (dest_str, None, None) # ...otherwise, defer to resolver.resolve_path. This handles the # following forms: # # /FOLDER/ # /ENTITYNAME # /FOLDER/ENTITYNAME # [PROJECT]: # [PROJECT]:/FOLDER/ # [PROJECT]:/ENTITYNAME # [PROJECT]:/FOLDER/ENTITYNAME return resolve_path(dest_str)
def path_completer(text, expected=None, classes=None, perm_level=None, include_current_proj=False, typespec=None, visibility=None): ''' :param text: String to tab-complete to a path matching the syntax project-name:folder/entity_or_folder_name :type text: string :param expected: "folder", "entity", "project", or None (no restriction) as to the types of answers to look for :type expected: string :param classes: if expected="entity", the possible data object classes that are acceptable :type classes: list of strings :param perm_level: the minimum permissions level required, e.g. "VIEW" or "CONTRIBUTE" :type perm_level: string :param include_current_proj: Indicate whether the current project's name should be a potential result :type include_current_proj: boolean :param visibility: Visibility with which to restrict the completion (one of "either", "visible", or "hidden") (default behavior is dependent on *text*) Returns a list of matches to the text and restricted by the requested parameters. ''' colon_pos = get_last_pos_of_char(':', text) slash_pos = get_last_pos_of_char('/', text) delim_pos = max(colon_pos, slash_pos) # First get projects if necessary matches = [] if expected == 'project' and colon_pos > 0 and colon_pos == len(text) - 1: if dxpy.find_one_project(zero_ok=True, name=text[:colon_pos]) is not None: return [text + " "] if colon_pos < 0 and slash_pos < 0: # Might be tab-completing a project, but don't ever include # whatever's set as dxpy.WORKSPACE_ID unless expected == "project" # Also, don't bother if text=="" and expected is NOT "project" # Also, add space if expected == "project" if text != "" or expected == 'project': results = dxpy.find_projects(describe=True, level=perm_level) if not include_current_proj: results = [r for r in results if r['id'] != dxpy.WORKSPACE_ID] matches += [escape_colon(r['describe']['name'])+':' for r in results if r['describe']['name'].startswith(text)] if expected == 'project': return matches # Attempt to tab-complete to a folder or data object name if colon_pos < 0 and slash_pos >= 0: # Not tab-completing a project, and the project is unambiguous # (use dxpy.WORKSPACE_ID) if dxpy.WORKSPACE_ID is not None: # try-catch block in case dxpy.WORKSPACE_ID is garbage try: dxproj = dxpy.get_handler(dxpy.WORKSPACE_ID) folderpath, entity_name = clean_folder_path(text) matches += get_folder_matches(text, slash_pos, dxproj, folderpath) if expected != 'folder': if classes is not None: for classname in classes: matches += get_data_matches(text, slash_pos, dxproj, folderpath, classname=classname, typespec=typespec, visibility=visibility) else: matches += get_data_matches(text, slash_pos, dxproj, folderpath, typespec=typespec, visibility=visibility) except: pass else: # project is given by a path, but attempt to resolve to an # object or folder anyway try: proj_ids, folderpath, entity_name = resolve_path(text, multi_projects=True) except ResolutionError as details: sys.stderr.write("\n" + fill(unicode(details))) return matches for proj in proj_ids: # protects against dxpy.WORKSPACE_ID being garbage try: dxproj = dxpy.get_handler(proj) matches += get_folder_matches(text, delim_pos, dxproj, folderpath) if expected != 'folder': if classes is not None: for classname in classes: matches += get_data_matches(text, delim_pos, dxproj, folderpath, classname=classname, typespec=typespec, visibility=visibility) else: matches += get_data_matches(text, delim_pos, dxproj, folderpath, typespec=typespec, visibility=visibility) except: pass return matches
def path_completer(text, expected=None, classes=None, perm_level=None, include_current_proj=False, typespec=None, visibility=None): ''' :param text: String to tab-complete to a path matching the syntax project-name:folder/entity_or_folder_name :type text: string :param expected: "folder", "entity", "project", or None (no restriction) as to the types of answers to look for :type expected: string :param classes: if expected="entity", the possible data object classes that are acceptable :type classes: list of strings :param perm_level: the minimum permissions level required, e.g. "VIEW" or "CONTRIBUTE" :type perm_level: string :param include_current_proj: Indicate whether the current project's name should be a potential result :type include_current_proj: boolean :param visibility: Visibility with which to restrict the completion (one of "either", "visible", or "hidden") (default behavior is dependent on *text*) Returns a list of matches to the text and restricted by the requested parameters. ''' colon_pos = get_last_pos_of_char(':', text) slash_pos = get_last_pos_of_char('/', text) delim_pos = max(colon_pos, slash_pos) # First get projects if necessary matches = [] if expected == 'project' and colon_pos > 0 and colon_pos == len(text) - 1: if dxpy.find_one_project(zero_ok=True, name=text[:colon_pos]) is not None: return [text + " "] if colon_pos < 0 and slash_pos < 0: # Might be tab-completing a project, but don't ever include # whatever's set as dxpy.WORKSPACE_ID unless expected == "project" # Also, don't bother if text=="" and expected is NOT "project" # Also, add space if expected == "project" if text != "" or expected == 'project': results = dxpy.find_projects(describe=True, level=perm_level) if not include_current_proj: results = [r for r in results if r['id'] != dxpy.WORKSPACE_ID] matches += [ escape_colon(r['describe']['name']) + ':' for r in results if r['describe']['name'].startswith(text) ] if expected == 'project': return matches # Attempt to tab-complete to a folder or data object name if colon_pos < 0 and slash_pos >= 0: # Not tab-completing a project, and the project is unambiguous # (use dxpy.WORKSPACE_ID) if dxpy.WORKSPACE_ID is not None: # try-catch block in case dxpy.WORKSPACE_ID is garbage try: dxproj = dxpy.get_handler(dxpy.WORKSPACE_ID) folderpath, entity_name = clean_folder_path(text) matches += get_folder_matches(text, slash_pos, dxproj, folderpath) if expected != 'folder': if classes is not None: for classname in classes: matches += get_data_matches(text, slash_pos, dxproj, folderpath, classname=classname, typespec=typespec, visibility=visibility) else: matches += get_data_matches(text, slash_pos, dxproj, folderpath, typespec=typespec, visibility=visibility) except: pass else: # project is given by a path, but attempt to resolve to an # object or folder anyway try: proj_ids, folderpath, entity_name = resolve_path( text, multi_projects=True) except ResolutionError as details: sys.stderr.write("\n" + fill(unicode(details))) return matches for proj in proj_ids: # protects against dxpy.WORKSPACE_ID being garbage try: dxproj = dxpy.get_handler(proj) matches += get_folder_matches(text, delim_pos, dxproj, folderpath) if expected != 'folder': if classes is not None: for classname in classes: matches += get_data_matches(text, delim_pos, dxproj, folderpath, classname=classname, typespec=typespec, visibility=visibility) else: matches += get_data_matches(text, delim_pos, dxproj, folderpath, typespec=typespec, visibility=visibility) except: pass return matches