Example #1
0
 def _run_binary(self, kwargs):
     if not self.cmd[0]:
         raise xt.XonshError("xonsh: subprocess mode: command is empty")
     bufsize = 1
     try:
         if xp.ON_WINDOWS and self.binary_loc is not None:
             # launch process using full paths (https://bugs.python.org/issue8557)
             cmd = [self.binary_loc] + self.cmd[1:]
         else:
             cmd = self.cmd
         p = self.cls(cmd, bufsize=bufsize, **kwargs)
     except PermissionError:
         e = "xonsh: subprocess mode: permission denied: {0}"
         raise xt.XonshError(e.format(self.cmd[0]))
     except FileNotFoundError:
         cmd0 = self.cmd[0]
         if len(self.cmd) == 1 and cmd0.endswith("?"):
             with contextlib.suppress(OSError):
                 return self.cls(["man", cmd0.rstrip("?")],
                                 bufsize=bufsize,
                                 **kwargs)
         e = "xonsh: subprocess mode: command not found: {0}".format(cmd0)
         env = XSH.env
         sug = xt.suggest_commands(cmd0, env)
         if len(sug.strip()) > 0:
             e += "\n" + xt.suggest_commands(cmd0, env)
         raise xt.XonshError(e)
     return p
Example #2
0
def _redirect_streams(r, loc=None):
    """Returns stdin, stdout, stderr tuple of redirections."""
    stdin = stdout = stderr = None
    no_ampersand = r.replace("&", "")
    # special case of redirecting stderr to stdout
    if no_ampersand in _E2O_MAP:
        stderr = subprocess.STDOUT
        return stdin, stdout, stderr
    elif no_ampersand in _O2E_MAP:
        stdout = 2  # using 2 as a flag, rather than using a file object
        return stdin, stdout, stderr
    # get streams
    orig, mode, dest = _parse_redirects(r)
    if mode == "r":
        stdin = safe_open(loc, mode)
    elif mode in _WRITE_MODES:
        if orig in _REDIR_ALL:
            stdout = stderr = safe_open(loc, mode)
        elif orig in _REDIR_OUT:
            stdout = safe_open(loc, mode)
        elif orig in _REDIR_ERR:
            stderr = safe_open(loc, mode)
        else:
            raise xt.XonshError(f"Unrecognized redirection command: {r}")
    else:
        raise xt.XonshError(f"Unrecognized redirection command: {r}")
    return stdin, stdout, stderr
Example #3
0
def safe_open(fname, mode, buffering=-1):
    """Safely attempts to open a file in for xonsh subprocs."""
    # file descriptors
    try:
        return io.open(fname, mode, buffering=buffering)
    except PermissionError:
        raise xt.XonshError(f"xonsh: {fname}: permission denied")
    except FileNotFoundError:
        raise xt.XonshError(f"xonsh: {fname}: no such file or directory")
    except Exception:
        raise xt.XonshError(f"xonsh: {fname}: unable to open file")
Example #4
0
def cmds_to_specs(cmds, captured=False, envs=None):
    """Converts a list of cmds to a list of SubprocSpec objects that are
    ready to be executed.
    """
    # first build the subprocs independently and separate from the redirects
    i = 0
    specs = []
    redirects = []
    for i, cmd in enumerate(cmds):
        if isinstance(cmd, str):
            redirects.append(cmd)
        else:
            env = envs[i] if envs is not None else None
            spec = SubprocSpec.build(cmd, captured=captured, env=env)
            spec.pipeline_index = i
            specs.append(spec)
            i += 1
    # now modify the subprocs based on the redirects.
    for i, redirect in enumerate(redirects):
        if redirect == "|":
            # these should remain integer file descriptors, and not Python
            # file objects since they connect processes.
            r, w = os.pipe()
            specs[i].stdout = w
            specs[i + 1].stdin = r
        elif redirect == "&" and i == len(redirects) - 1:
            specs[i].background = True
        else:
            raise xt.XonshError(f"unrecognized redirect {redirect!r}")
    # Apply boundary conditions
    _update_last_spec(specs[-1])
    return specs
Example #5
0
 def stderr(self, value):
     if self._stderr is None:
         self._stderr = value
     elif value is None:
         pass
     else:
         safe_close(value)
         msg = "Multiple redirections for stderr for {0!r}"
         msg = msg.format(" ".join(self.args))
         raise xt.XonshError(msg)
Example #6
0
 def stdin(self, value):
     if self._stdin is None:
         self._stdin = value
     elif value is None:
         pass
     else:
         safe_close(value)
         msg = "Multiple inputs for stdin for {0!r}"
         msg = msg.format(" ".join(self.args))
         raise xt.XonshError(msg)
Example #7
0
 def _run_binary(self, kwargs):
     try:
         bufsize = 1
         p = self.cls(self.cmd, bufsize=bufsize, **kwargs)
     except PermissionError:
         e = "xonsh: subprocess mode: permission denied: {0}"
         raise xt.XonshError(e.format(self.cmd[0]))
     except FileNotFoundError:
         cmd0 = self.cmd[0]
         if len(self.cmd) == 1 and cmd0.endswith("?"):
             with contextlib.suppress(OSError):
                 return self.cls(["man", cmd0.rstrip("?")],
                                 bufsize=bufsize,
                                 **kwargs)
         e = "xonsh: subprocess mode: command not found: {0}".format(cmd0)
         env = builtins.__xonsh__.env
         sug = xt.suggest_commands(cmd0, env, builtins.aliases)
         if len(sug.strip()) > 0:
             e += "\n" + xt.suggest_commands(cmd0, env, builtins.aliases)
         raise xt.XonshError(e)
     return p
Example #8
0
def _parse_redirects(r, loc=None):
    """returns origin, mode, destination tuple"""
    orig, mode, dest = _REDIR_REGEX.match(r).groups()
    # redirect to fd
    if dest.startswith("&"):
        try:
            dest = int(dest[1:])
            if loc is None:
                loc, dest = dest, ""  # NOQA
            else:
                e = f"Unrecognized redirection command: {r}"
                raise xt.XonshError(e)
        except (ValueError, xt.XonshError):
            raise
        except Exception:
            pass
    mode = _MODES.get(mode, None)
    if mode == "r" and (len(orig) > 0 or len(dest) > 0):
        raise xt.XonshError(f"Unrecognized redirection command: {r}")
    elif mode in _WRITE_MODES and len(dest) > 0:
        raise xt.XonshError(f"Unrecognized redirection command: {r}")
    return orig, mode, dest
Example #9
0
def partial_proxy(f):
    """Dispatches the appropriate proxy function based on the number of args."""
    numargs = 0
    for name, param in inspect.signature(f).parameters.items():
        if (param.kind == param.POSITIONAL_ONLY
                or param.kind == param.POSITIONAL_OR_KEYWORD):
            numargs += 1
        elif name in xt.ALIAS_KWARG_NAMES and param.kind == param.KEYWORD_ONLY:
            numargs += 1
    if numargs < 6:
        return functools.partial(PROXIES[numargs], f)
    elif numargs == 6:
        # don't need to partial.
        return f
    else:
        e = "Expected proxy with 6 or fewer arguments for {}, not {}"
        raise xt.XonshError(e.format(", ".join(xt.ALIAS_KWARG_NAMES), numargs))
Example #10
0
def cmds_to_specs(cmds, captured=False, envs=None):
    """Converts a list of cmds to a list of SubprocSpec objects that are
    ready to be executed.
    """
    # first build the subprocs independently and separate from the redirects
    i = 0
    specs = []
    redirects = []
    for i, cmd in enumerate(cmds):
        if isinstance(cmd, str):
            redirects.append(cmd)
        else:
            env = envs[i] if envs is not None else None
            spec = SubprocSpec.build(cmd, captured=captured, env=env)
            spec.pipeline_index = i
            specs.append(spec)
            i += 1
    # now modify the subprocs based on the redirects.
    for i, redirect in enumerate(redirects):
        if redirect == "|":
            # these should remain integer file descriptors, and not Python
            # file objects since they connect processes.
            r, w = os.pipe()
            specs[i].stdout = w
            specs[i + 1].stdin = r
        elif redirect == "&" and i == len(redirects) - 1:
            specs[i].background = True
        else:
            raise xt.XonshError(f"unrecognized redirect {redirect!r}")

    # Apply boundary conditions
    if not XSH.env.get("XONSH_CAPTURE_ALWAYS"):
        # Make sure sub-specs are always captured.
        # I.e. ![some_alias | grep x] $(some_alias)
        specs_to_capture = specs if captured in STDOUT_CAPTURE_KINDS else specs[:
                                                                                -1]
        for spec in specs_to_capture:
            if spec.env is None:
                spec.env = {"XONSH_CAPTURE_ALWAYS": True}
            else:
                spec.env.setdefault("XONSH_CAPTURE_ALWAYS", True)

    _update_last_spec(specs[-1])
    return specs
Example #11
0
 def build(kls, cmd, *, cls=subprocess.Popen, **kwargs):
     """Creates an instance of the subprocess command, with any
     modifications and adjustments based on the actual cmd that
     was received.
     """
     if not cmd:
         raise xt.XonshError("xonsh: subprocess mode: command is empty")
     # modifications that do not alter cmds may come before creating instance
     spec = kls(cmd, cls=cls, **kwargs)
     # modifications that alter cmds must come after creating instance
     # perform initial redirects
     spec.redirect_leading()
     spec.redirect_trailing()
     # apply aliases
     spec.resolve_alias()
     spec.resolve_binary_loc()
     spec.resolve_auto_cd()
     spec.resolve_executable_commands()
     spec.resolve_alias_cls()
     spec.resolve_stack()
     return spec
Example #12
0
 def resolve_executable_commands(self):
     """Resolve command executables, if applicable."""
     alias = self.alias
     if alias is None:
         pass
     elif callable(alias):
         self.cmd.pop(0)
         return
     else:
         self.cmd = alias + self.cmd[1:]
         # resolve any redirects the aliases may have applied
         self.redirect_leading()
         self.redirect_trailing()
     if self.binary_loc is None:
         return
     try:
         scriptcmd = get_script_subproc_command(self.binary_loc, self.cmd[1:])
         if scriptcmd is not None:
             self.cmd = scriptcmd
     except PermissionError:
         e = "xonsh: subprocess mode: permission denied: {0}"
         raise xt.XonshError(e.format(self.cmd[0]))