def test_iglobpath(): with TemporaryDirectory() as test_dir: # Create files 00.test to 99.test in unsorted order num = 18 for _ in range(100): s = str(num).zfill(2) path = os.path.join(test_dir, s + '.test') with open(path, 'w') as file: file.write(s + '\n') num = (num + 37) % 100 # Create one file not matching the '*.test' with open(os.path.join(test_dir, '07'), 'w') as file: file.write('test\n') with mock_xonsh_env(Env(EXPAND_ENV_VARS=False)): builtins.__xonsh_expand_path__ = expand_path paths = list(iglobpath(os.path.join(test_dir, '*.test'), ignore_case=False, sort_result=False)) assert len(paths) == 100 paths = list(iglobpath(os.path.join(test_dir, '*'), ignore_case=True, sort_result=False)) assert len(paths) == 101 paths = list(iglobpath(os.path.join(test_dir, '*.test'), ignore_case=False, sort_result=True)) assert len(paths) == 100 assert paths == sorted(paths) paths = list(iglobpath(os.path.join(test_dir, '*'), ignore_case=True, sort_result=True)) assert len(paths) == 101 assert paths == sorted(paths)
def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = '' path_str_end = '' append_end = True p = _path_from_partial_string(line, end) lprefix = len(prefix) if p is not None: lprefix = len(p[0]) prefix = p[1] path_str_start = p[2] path_str_end = p[3] if len(line) >= end + 1 and line[end] == path_str_end: append_end = False tilde = '~' paths = set() env = builtins.__xonsh_env__ csc = env.get('CASE_SENSITIVE_COMPLETIONS') glob_sorted = env.get('GLOB_SORTED') prefix = glob.escape(prefix) for s in xt.iglobpath(prefix + '*', ignore_case=(not csc), sort_result=glob_sorted): paths.add(s) if len(paths) == 0 and env.get('SUBSEQUENCE_PATH_COMPLETION'): # this block implements 'subsequence' matching, similar to fish and zsh. # matches are based on subsequences, not substrings. # e.g., ~/u/ro completes to ~/lou/carcolh # see above functions for details. p = _splitpath(os.path.expanduser(prefix)) if len(p) != 0: if p[0] == '': basedir = ('', ) p = p[1:] else: basedir = None matches_so_far = {basedir} for i in p: matches_so_far = _expand_one(matches_so_far, i, csc) paths |= {_joinpath(i) for i in matches_so_far} if len(paths) == 0 and env.get('FUZZY_PATH_COMPLETION'): threshold = env.get('SUGGEST_THRESHOLD') for s in xt.iglobpath(os.path.dirname(prefix) + '*', ignore_case=(not csc), sort_result=glob_sorted): if xt.levenshtein(prefix, s, threshold) < threshold: paths.add(s) if tilde in prefix: home = os.path.expanduser(tilde) paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) paths = set(filter(filtfunc, paths)) paths, _ = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end, append_end) paths.update(filter(filtfunc, _dots(prefix))) paths.update(filter(filtfunc, _env(prefix))) return paths, lprefix
def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = '' path_str_end = '' append_end = True p = _path_from_partial_string(line, end) lprefix = len(prefix) if p is not None: lprefix = len(p[0]) prefix = p[1] path_str_start = p[2] path_str_end = p[3] if len(line) >= end + 1 and line[end] == path_str_end: append_end = False tilde = '~' paths = set() env = builtins.__xonsh_env__ csc = env.get('CASE_SENSITIVE_COMPLETIONS') glob_sorted = env.get('GLOB_SORTED') prefix = glob.escape(prefix) for s in xt.iglobpath(prefix + '*', ignore_case=(not csc), sort_result=glob_sorted): paths.add(s) if len(paths) == 0 and env.get('SUBSEQUENCE_PATH_COMPLETION'): # this block implements 'subsequence' matching, similar to fish and zsh. # matches are based on subsequences, not substrings. # e.g., ~/u/ro completes to ~/lou/carcolh # see above functions for details. p = _splitpath(os.path.expanduser(prefix)) if len(p) != 0: if p[0] == '': basedir = ('', ) p = p[1:] else: basedir = None matches_so_far = {basedir} for i in p: matches_so_far = _expand_one(matches_so_far, i, csc) paths |= {_joinpath(i) for i in matches_so_far} if len(paths) == 0 and env.get('FUZZY_PATH_COMPLETION'): threshold = env.get('SUGGEST_THRESHOLD') for s in xt.iglobpath(os.path.dirname(prefix) + '*', ignore_case=(not csc), sort_result=glob_sorted): if xt.levenshtein(prefix, s, threshold) < threshold: paths.add(s) if tilde in prefix: home = os.path.expanduser(tilde) paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) paths = set(filter(filtfunc, paths)) paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end, append_end) paths.update(filter(filtfunc, _dots(prefix))) paths.update(filter(filtfunc, _env(prefix))) return paths, lprefix
def complete_path(prefix, line, start, end, ctx, cdpath=True): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = "" path_str_end = "" p = _path_from_partial_string(line, end) lprefix = len(prefix) if p is not None: lprefix = len(p[0]) prefix = p[1] path_str_start = p[2] path_str_end = p[3] tilde = "~" paths = set() csc = builtins.__xonsh_env__.get("CASE_SENSITIVE_COMPLETIONS") for s in iglobpath(prefix + "*", ignore_case=(not csc)): paths.add(s) if tilde in prefix: home = os.path.expanduser(tilde) paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end) _add_env(paths, prefix) _add_dots(paths, prefix) return paths, lprefix
def complete_path(prefix, line, start, end, ctx, cdpath=True): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = '' path_str_end = '' p = _path_from_partial_string(line, end) lprefix = len(prefix) if p is not None: lprefix = len(p[0]) prefix = p[1] path_str_start = p[2] path_str_end = p[3] tilde = '~' paths = set() csc = builtins.__xonsh_env__.get('CASE_SENSITIVE_COMPLETIONS') for s in iglobpath(prefix + '*', ignore_case=(not csc)): paths.add(s) if tilde in prefix: home = os.path.expanduser(tilde) paths = {s.replace(home, tilde) for s in paths} if cdpath: _add_cdpaths(paths, prefix) paths = _quote_paths({_normpath(s) for s in paths}, path_str_start, path_str_end) _add_env(paths, prefix) _add_dots(paths, prefix) return paths, lprefix
def _add_cdpaths(paths, prefix): """Completes current prefix using CDPATH""" env = builtins.__xonsh_env__ csc = env.get('CASE_SENSITIVE_COMPLETIONS') for cdp in env.get('CDPATH'): test_glob = os.path.join(cdp, prefix) + '*' for s in iglobpath(test_glob, ignore_case=(not csc)): if os.path.isdir(s): paths.add(os.path.basename(s))
def _expand_one(sofar, nextone, csc): out = set() for i in sofar: _glob = os.path.join(_joinpath(i), '*') if i is not None else '*' for j in iglobpath(_glob): j = os.path.basename(j) if subsequence_match(j, nextone, csc): out.add((i or ()) + (j, )) return out
def _add_cdpaths(paths, prefix): """Completes current prefix using CDPATH""" env = builtins.__xonsh_env__ csc = env.get("CASE_SENSITIVE_COMPLETIONS") for cdp in env.get("CDPATH"): test_glob = os.path.join(cdp, prefix) + "*" for s in iglobpath(test_glob, ignore_case=(not csc)): if os.path.isdir(s): paths.add(os.path.basename(s))
def _expand_one(sofar, nextone, csc): out = set() glob_sorted = XSH.env.get("GLOB_SORTED") for i in sofar: _glob = os.path.join(_joinpath(i), "*") if i is not None else "*" for j in xt.iglobpath(_glob, sort_result=glob_sorted): j = os.path.basename(j) if subsequence_match(j, nextone, csc): out.add((i or ()) + (j, )) return out
def _expand_one(sofar, nextone, csc): out = set() glob_sorted = builtins.__xonsh_env__.get('GLOB_SORTED') for i in sofar: _glob = os.path.join(_joinpath(i), '*') if i is not None else '*' for j in xt.iglobpath(_glob, sort_result=glob_sorted): j = os.path.basename(j) if subsequence_match(j, nextone, csc): out.add((i or ()) + (j, )) return out
def _add_cdpaths(paths, prefix): """Completes current prefix using CDPATH""" env = builtins.__xonsh_env__ csc = env.get('CASE_SENSITIVE_COMPLETIONS') glob_sorted = env.get('GLOB_SORTED') for cdp in env.get('CDPATH'): test_glob = os.path.join(cdp, prefix) + '*' for s in xt.iglobpath(test_glob, ignore_case=(not csc), sort_result=glob_sorted): if os.path.isdir(s): paths.add(os.path.basename(s))
def test_iglobpath_empty_str(monkeypatch, xonsh_builtins): # makes sure that iglobpath works, even when os.scandir() and os.listdir() # fail to return valid results, like an empty filename def mockscandir(path): yield '' if hasattr(os, 'scandir'): monkeypatch.setattr(os, 'scandir', mockscandir) def mocklistdir(path): return [''] monkeypatch.setattr(os, 'listdir', mocklistdir) paths = list(iglobpath('some/path')) assert len(paths) == 0
def _add_cdpaths(paths, prefix): """Completes current prefix using CDPATH""" env = builtins.__xonsh__.env csc = env.get("CASE_SENSITIVE_COMPLETIONS") glob_sorted = env.get("GLOB_SORTED") for cdp in env.get("CDPATH"): test_glob = os.path.join(cdp, prefix) + "*" for s in xt.iglobpath( test_glob, ignore_case=(not csc), sort_result=glob_sorted ): if os.path.isdir(s): paths.add(os.path.relpath(s, cdp))
def test_iglobpath_empty_str(monkeypatch, xession): # makes sure that iglobpath works, even when os.scandir() and os.listdir() # fail to return valid results, like an empty filename def mockscandir(path): yield "" if hasattr(os, "scandir"): monkeypatch.setattr(os, "scandir", mockscandir) def mocklistdir(path): return [""] monkeypatch.setattr(os, "listdir", mocklistdir) paths = list(iglobpath("some/path")) assert len(paths) == 0
def complete_path(prefix, line, start, end, ctx, cdpath=True, filtfunc=None): """Completes based on a path name.""" # string stuff for automatic quoting path_str_start = "" path_str_end = "" append_end = True p = _path_from_partial_string(line, end) lprefix = len(prefix) if p is not None: lprefix = len(p[0]) # Compensate for 'p' if p-string variant pstring_pre = _get_normalized_pstring_quote(p[2])[0] if pstring_pre in ("pr", "p"): lprefix += 1 prefix = p[1] path_str_start = p[2] path_str_end = p[3] if len(line) >= end + 1 and line[end] == path_str_end: append_end = False tilde = "~" paths = set() env = builtins.__xonsh__.env csc = env.get("CASE_SENSITIVE_COMPLETIONS") glob_sorted = env.get("GLOB_SORTED") prefix = glob.escape(prefix) for s in xt.iglobpath(prefix + "*", ignore_case=(not csc), sort_result=glob_sorted): paths.add(s) if len(paths) == 0 and env.get("SUBSEQUENCE_PATH_COMPLETION"): # this block implements 'subsequence' matching, similar to fish and zsh. # matches are based on subsequences, not substrings. # e.g., ~/u/ro completes to ~/lou/carcolh # see above functions for details. p = _splitpath(os.path.expanduser(prefix)) p_len = len(p) if p_len != 0: relative_char = ["", ".", ".."] if p[0] in relative_char: i = 0 while i < p_len and p[i] in relative_char: i += 1 basedir = p[:i] p = p[i:] else: basedir = None matches_so_far = {basedir} for i in p: matches_so_far = _expand_one(matches_so_far, i, csc) paths |= {_joinpath(i) for i in matches_so_far} if len(paths) == 0 and env.get("FUZZY_PATH_COMPLETION"): threshold = env.get("SUGGEST_THRESHOLD") for s in xt.iglobpath( os.path.dirname(prefix) + "*", ignore_case=(not csc), sort_result=glob_sorted, ): if xt.levenshtein(prefix, s, threshold) < threshold: paths.add(s) if cdpath and cd_in_command(line): _add_cdpaths(paths, prefix) paths = set(filter(filtfunc, paths)) if tilde in prefix: home = os.path.expanduser(tilde) paths = {s.replace(home, tilde) for s in paths} paths, _ = _quote_paths( {_normpath(s) for s in paths}, path_str_start, path_str_end, append_end, cdpath ) paths.update(filter(filtfunc, _dots(prefix))) paths.update(filter(filtfunc, _env(prefix))) return paths, lprefix
def test_iglobpath_no_dotfiles_recursive(xession): d = os.path.dirname(__file__) g = d + "/**" files = list(iglobpath(g, include_dotfiles=False)) assert d + "/bin/.someotherdotfile" not in files
def test_iglobpath_dotfiles(xonsh_builtins): d = os.path.dirname(__file__) g = d + "/*" files = list(iglobpath(g, include_dotfiles=True)) assert d + "/.somedotfile" in files
def test_iglobpath_dotfiles_recursive(xonsh_builtins): d = os.path.dirname(__file__) g = d + "/**" files = list(iglobpath(g, include_dotfiles=True)) assert d + "/bin/.someotherdotfile" in files
def test_iglobpath_no_dotfiles(xession): d = os.path.dirname(__file__) g = d + "/*" files = list(iglobpath(g, include_dotfiles=False)) assert d + "/.somedotfile" not in files