def _yield_executables(directory, name): if ON_WINDOWS: base_name, ext = os.path.splitext(name.lower()) for fname in executables_in(directory): fbase, fext = os.path.splitext(fname.lower()) if base_name == fbase and (len(ext) == 0 or ext == fext): yield os.path.join(directory, fname) else: for x in executables_in(directory): if x == name: yield os.path.join(directory, name) return
def complete_command(cmd, line, start, end, ctx): """ Returns a list of valid commands starting with the first argument """ space = " " out = {s + space for s in builtins.__xonsh_commands_cache__ if get_filter_function()(s, cmd)} if xp.ON_WINDOWS: out |= {i for i in xt.executables_in(".") if i.startswith(cmd)} base = os.path.basename(cmd) if os.path.isdir(base): out |= {os.path.join(base, i) for i in xt.executables_in(base) if i.startswith(cmd)} return out
def test_executables_in(): expected = set() types = ('file', 'directory', 'brokensymlink') executables = (True, False) with TemporaryDirectory() as test_path: for _type in types: for executable in executables: fname = '%s_%s' % (_type, executable) if _type == 'none': continue if _type == 'file' and executable: ext = '.exe' if ON_WINDOWS else '' expected.add(fname + ext) else: ext = '' path = os.path.join(test_path, fname + ext) if _type == 'file': with open(path, 'w') as f: f.write(fname) elif _type == 'directory': os.mkdir(path) elif _type == 'brokensymlink': tmp_path = os.path.join(test_path, 'i_wont_exist') with open(tmp_path, 'w') as f: f.write('deleteme') os.symlink(tmp_path, path) os.remove(tmp_path) if executable and not _type == 'brokensymlink': os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) result = set(executables_in(test_path)) assert_equal(expected, result)
def _update_cmds_cache(self, paths: tp.Sequence[str], aliases: tp.Dict[str, str]) -> tp.Dict[str, tp.Any]: """Update the cmds_cache variable in background without slowing down parseLexer""" env = builtins.__xonsh__.env # type: ignore allcmds = {} for path in reversed(paths): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (os.path.join(path, cmd), aliases.get(key, None)) warn_cnt = env.get("COMMANDS_CACHE_SIZE_WARNING") if warn_cnt and len(allcmds) > warn_cnt: print( f"Warning! Found {len(allcmds):,} executable files in the PATH directories!", file=sys.stderr, ) for cmd in aliases: if cmd not in allcmds: key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (cmd, True) # type: ignore return self.set_cmds_cache(allcmds)
def all_commands(self): paths = builtins.__xonsh_env__.get('PATH', []) pathset = frozenset(x for x in paths if os.path.isdir(x)) # did PATH change? path_hash = hash(pathset) cache_valid = path_hash == self._path_checksum self._path_checksum = path_hash # did aliases change? alss = getattr(builtins, 'aliases', set()) al_hash = hash(frozenset(alss)) cache_valid = cache_valid and al_hash == self._alias_checksum self._alias_checksum = al_hash # did the contents of any directory in PATH change? max_mtime = 0 for path in pathset: mtime = os.stat(path).st_mtime if mtime > max_mtime: max_mtime = mtime cache_valid = cache_valid and (max_mtime <= self._path_mtime) self._path_mtime = max_mtime if cache_valid: return self._cmds_cache allcmds = {} for path in reversed(paths): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (os.path.join(path, cmd), cmd in alss) only_alias = (None, True) for cmd in alss: if cmd not in allcmds: allcmds[cmd] = only_alias self._cmds_cache = allcmds return allcmds
def test_executables_in(): expected = set() types = ('file', 'directory', 'brokensymlink') executables = (True, False) with TemporaryDirectory() as test_path: for _type in types: for executable in executables: fname = '%s_%s' % (_type, executable) if _type == 'none': continue if _type == 'file' and executable: ext = '.exe' if ON_WINDOWS else '' expected.add(fname + ext) else: ext = '' path = os.path.join(test_path, fname + ext) if _type == 'file': with open(path, 'w') as f: f.write(fname) elif _type == 'directory': os.mkdir(path) elif _type == 'brokensymlink': tmp_path = os.path.join(test_path, 'i_wont_exist') with open(tmp_path,'w') as f: f.write('deleteme') os.symlink(tmp_path, path) os.remove(tmp_path) if executable and not _type == 'brokensymlink' : os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) result = set(executables_in(test_path)) assert_equal(expected, result)
def test_executables_in(): expected = set() types = ('none', 'file', 'file', 'directory') executables = (True, True, False) with TemporaryDirectory() as test_path: for i in range(64): _type = types[i%len(types)] if _type == 'none': continue executable = executables[i%len(executables)] if _type == 'file' and executable: ext = '.exe' if ON_WINDOWS else '' expected.add(str(i) + ext) else: ext = '' path = os.path.join(test_path, str(i) + ext) if _type == 'file': with open(path, 'w') as f: f.write(str(i)) elif _type == 'directory': os.mkdir(path) if executable: os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) result = set(executables_in(test_path)) assert_equal(expected, result)
def all_commands(self): paths = builtins.__xonsh_env__.get('PATH', []) pathset = frozenset(x for x in paths if os.path.isdir(x)) # did PATH change? path_hash = hash(pathset) cache_valid = path_hash == self._path_checksum self._path_checksum = path_hash # did aliases change? alss = getattr(builtins, 'aliases', dict()) al_hash = hash(frozenset(alss)) cache_valid = cache_valid and al_hash == self._alias_checksum self._alias_checksum = al_hash # did the contents of any directory in PATH change? max_mtime = 0 for path in pathset: mtime = os.stat(path).st_mtime if mtime > max_mtime: max_mtime = mtime cache_valid = cache_valid and (max_mtime <= self._path_mtime) self._path_mtime = max_mtime if cache_valid: return self._cmds_cache allcmds = {} for path in reversed(paths): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (os.path.join(path, cmd), alss.get(key, None)) for cmd in alss: if cmd not in allcmds: key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (cmd, True) self._cmds_cache = allcmds return allcmds
def complete_command(cmd, line, start, end, ctx): """ Returns a list of valid commands starting with the first argument """ space = ' ' out = {s + space for s in builtins.__xonsh_commands_cache__ if get_filter_function()(s, cmd)} if ON_WINDOWS: out |= {i for i in executables_in('.') if i.startswith(cmd)} base = os.path.basename(cmd) if os.path.isdir(base): out |= {os.path.join(base, i) for i in executables_in(base) if i.startswith(cmd)} return out
def all_commands(self): paths = builtins.__xonsh__.env.get("PATH", []) paths = CommandsCache.remove_dups(paths) path_immut = tuple(x for x in paths if os.path.isdir(x)) # did PATH change? path_hash = hash(path_immut) cache_valid_path = path_hash == self._path_checksum self._path_checksum = path_hash # did aliases change? alss = getattr(builtins, "aliases", dict()) al_hash = hash(frozenset(alss)) cache_valid_aliases = al_hash == self._alias_checksum self._alias_checksum = al_hash # did the contents of any directory in PATH change? max_mtime = 0 for path in path_immut: mtime = os.stat(path).st_mtime if mtime > max_mtime: max_mtime = mtime cache_valid_paths = max_mtime <= self._path_mtime self._path_mtime = max_mtime if cache_valid_path and cache_valid_paths: if not cache_valid_aliases: for cmd, alias in alss.items(): key = cmd.upper() if ON_WINDOWS else cmd if key in self._cmds_cache: self._cmds_cache[key] = (self._cmds_cache[key][0], alias) else: self._cmds_cache[key] = (cmd, True) return self._cmds_cache allcmds = {} for path in reversed(path_immut): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (os.path.join(path, cmd), alss.get(key, None)) warn_cnt = builtins.__xonsh__.env.get("COMMANDS_CACHE_SIZE_WARNING") if warn_cnt: cnt = len(allcmds) if cnt > warn_cnt: print( f"Warning! Found {cnt:,} executable files in the PATH directories!", file=sys.stderr, ) for cmd in alss: if cmd not in allcmds: key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (cmd, True) self._cmds_cache = allcmds return allcmds
def complete_command(command: CommandContext): """ Returns a list of valid commands starting with the first argument """ cmd = command.prefix out: tp.Set[Completion] = { RichCompletion(s, append_space=True) for s in builtins.__xonsh__.commands_cache # type: ignore if get_filter_function()(s, cmd) } if xp.ON_WINDOWS: out |= {i for i in xt.executables_in(".") if i.startswith(cmd)} base = os.path.basename(cmd) if os.path.isdir(base): out |= { os.path.join(base, i) for i in xt.executables_in(base) if i.startswith(cmd) } return out
def complete_command(command: CommandContext): """ Returns a list of valid commands starting with the first argument """ cmd = command.prefix show_desc = (XSH.env or {}).get("CMD_COMPLETIONS_SHOW_DESC", False) for s, (path, is_alias) in XSH.commands_cache.iter_commands(): if get_filter_function()(s, cmd): kwargs = {} if show_desc: kwargs["description"] = "Alias" if is_alias else path yield RichCompletion(s, append_space=True, **kwargs) if xp.ON_WINDOWS: for i in xt.executables_in("."): if i.startswith(cmd): yield RichCompletion(i, append_space=True) base = os.path.basename(cmd) if os.path.isdir(base): for i in xt.executables_in(base): if i.startswith(cmd): yield RichCompletion(os.path.join(base, i))
def test_executables_in(xonsh_builtins): expected = set() types = ("file", "directory", "brokensymlink") if ON_WINDOWS: # Don't test symlinks on windows since it requires admin types = ("file", "directory") executables = (True, False) with TemporaryDirectory() as test_path: for _type in types: for executable in executables: fname = "%s_%s" % (_type, executable) if _type == "none": continue if _type == "file" and executable: ext = ".exe" if ON_WINDOWS else "" expected.add(fname + ext) else: ext = "" path = os.path.join(test_path, fname + ext) if _type == "file": with open(path, "w") as f: f.write(fname) elif _type == "directory": os.mkdir(path) elif _type == "brokensymlink": tmp_path = os.path.join(test_path, "i_wont_exist") with open(tmp_path, "w") as f: f.write("deleteme") os.symlink(tmp_path, path) os.remove(tmp_path) if executable and not _type == "brokensymlink": os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) if ON_WINDOWS: xonsh_builtins.__xonsh__.env = PATHEXT_ENV result = set(executables_in(test_path)) else: result = set(executables_in(test_path)) assert expected == result
def test_executables_in(xonsh_builtins): expected = set() types = ('file', 'directory', 'brokensymlink') if ON_WINDOWS: # Don't test symlinks on windows since it requires admin types = ('file', 'directory') executables = (True, False) with TemporaryDirectory() as test_path: for _type in types: for executable in executables: fname = '%s_%s' % (_type, executable) if _type == 'none': continue if _type == 'file' and executable: ext = '.exe' if ON_WINDOWS else '' expected.add(fname + ext) else: ext = '' path = os.path.join(test_path, fname + ext) if _type == 'file': with open(path, 'w') as f: f.write(fname) elif _type == 'directory': os.mkdir(path) elif _type == 'brokensymlink': tmp_path = os.path.join(test_path, 'i_wont_exist') with open(tmp_path, 'w') as f: f.write('deleteme') os.symlink(tmp_path, path) os.remove(tmp_path) if executable and not _type == 'brokensymlink': os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) if ON_WINDOWS: xonsh_builtins.__xonsh_env__ = PATHEXT_ENV result = set(executables_in(test_path)) else: result = set(executables_in(test_path)) assert expected == result
def test_executables_in(): expected = set() with TemporaryDirectory() as test_path: for i in range(random.randint(100, 200)): _type = random.choice(('none', 'file', 'file', 'directory')) if _type == 'none': continue executable = random.choice((True, True, False)) if _type == 'file' and executable: expected.add(str(i)) path = os.path.join(test_path, str(i)) if _type == 'file': open(path, 'w').close() elif _type == 'directory': os.mkdir(path) if executable: os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) result = set(executables_in(test_path)) assert_equal(expected, result)
def all_commands(self): paths = builtins.__xonsh__.env.get("PATH", []) paths = CommandsCache.remove_dups(paths) path_immut = tuple(x for x in paths if os.path.isdir(x)) # did PATH change? path_hash = hash(path_immut) cache_valid = path_hash == self._path_checksum self._path_checksum = path_hash # did aliases change? alss = getattr(builtins, "aliases", dict()) al_hash = hash(frozenset(alss)) cache_valid = cache_valid and al_hash == self._alias_checksum self._alias_checksum = al_hash # did the contents of any directory in PATH change? max_mtime = 0 for path in path_immut: mtime = os.stat(path).st_mtime if mtime > max_mtime: max_mtime = mtime cache_valid = cache_valid and (max_mtime <= self._path_mtime) self._path_mtime = max_mtime if cache_valid: return self._cmds_cache allcmds = {} for path in reversed(path_immut): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (os.path.join(path, cmd), alss.get(key, None)) for cmd in alss: if cmd not in allcmds: key = cmd.upper() if ON_WINDOWS else cmd allcmds[key] = (cmd, True) self._cmds_cache = allcmds return allcmds
def _getter(): for path in reversed(paths): # iterate backwards so that entries at the front of PATH overwrite # entries at the back. for cmd in executables_in(path): yield cmd, os.path.join(path, cmd)