Blame lib/dbtexmf/core/commander.py

Packit Service 76cb02
import os
Packit Service 76cb02
from subprocess import Popen, PIPE
Packit Service cd7d79
from io import open
Packit Service 76cb02
Packit Service 76cb02
class Command:
Packit Service 76cb02
    """Contains the needed data to run a command"""
Packit Service 76cb02
    def __init__(self, args, stdin=None, stdout=None, shell=False):
Packit Service 76cb02
        self.arguments = args
Packit Service 76cb02
        self.stdin = stdin
Packit Service 76cb02
        self.stdout = stdout
Packit Service 76cb02
        self.shell = shell
Packit Service 76cb02
Packit Service 76cb02
class CommandRunner:
Packit Service 76cb02
    """
Packit Service 76cb02
    Execute the differents registered commands in the specified order,
Packit Service 76cb02
    either independantly or as a pipe process chain if required
Packit Service 76cb02
    """
Packit Service 76cb02
    def __init__(self, module_name="", log=None):
Packit Service 76cb02
        self.module_name = module_name
Packit Service 76cb02
        self.commands = []
Packit Service 76cb02
        self.processes = []
Packit Service 76cb02
        self.log = log
Packit Service 76cb02
Packit Service 76cb02
    def info(self, text):
Packit Service 76cb02
        if self.log: self.log.info(text)
Packit Service 76cb02
Packit Service 76cb02
    def set_name(self, module_name):
Packit Service 76cb02
        self.module_name = module_name
Packit Service 76cb02
Packit Service 76cb02
    def add_command(self, args, stdin=None, stdout=None, shell=False):
Packit Service 76cb02
        command = Command(args, stdin, stdout, shell)
Packit Service 76cb02
        self.commands.append(command)
Packit Service 76cb02
        return command
Packit Service 76cb02
Packit Service 76cb02
    def shcmd(self, args):
Packit Service 76cb02
        nargs = []
Packit Service 76cb02
        for arg in args:
Packit Service 76cb02
            if len(arg.split()) > 1: arg = '"%s"' % arg
Packit Service 76cb02
            nargs.append(arg)
Packit Service 76cb02
        return " ".join(nargs)
Packit Service 76cb02
Packit Service 76cb02
    def run(self, kw=None):
Packit Service 76cb02
        if not(self.commands):
Packit Service 76cb02
            return
Packit Service 76cb02
        if not(kw): kw = {}
Packit Service 76cb02
        pipe_top = False
Packit Service 76cb02
        rc = 0
Packit Service 76cb02
        for cmd in self.commands:
Packit Service 76cb02
            if rc != 0:
Packit Service 76cb02
                break
Packit Service 76cb02
            stdin, stdout = None, None
Packit Service 76cb02
            prev_pipe = None
Packit Service 76cb02
            if cmd.stdin == "PIPE":
Packit Service 76cb02
                if self.processes:
Packit Service 76cb02
                    prev_pipe = self.processes[-1]
Packit Service 76cb02
                    stdin = prev_pipe.stdout
Packit Service 76cb02
                else:
Packit Service 76cb02
                    pipe_top = True
Packit Service 76cb02
                    stdin = PIPE
Packit Service 76cb02
            if cmd.stdout == "PIPE":
Packit Service 76cb02
                stdout = PIPE
Packit Service 76cb02
            elif cmd.stdout:
Packit Service cd7d79
                stdout = open(cmd.stdout % kw, "wb")
Packit Service 76cb02
Packit Service 76cb02
            if kw: args = [a % kw for a in cmd.arguments]
Packit Service 76cb02
            else: args = cmd.arguments
Packit Service 76cb02
            
Packit Service 76cb02
            self.info(" ".join(args))
Packit Service 76cb02
            # Some commands work only in shell env (e.g. links), so take care
Packit Service 76cb02
            if cmd.shell:
Packit Service 76cb02
                p = Popen(self.shcmd(args), stdin=stdin, stdout=stdout,
Packit Service 76cb02
                          shell=True)
Packit Service 76cb02
            else:
Packit Service 76cb02
                p = Popen(args, stdin=stdin, stdout=stdout)
Packit Service 76cb02
            self.processes.append(p)
Packit Service 76cb02
Packit Service 76cb02
            if stdin and prev_pipe:
Packit Service 76cb02
                # Close stdout to allow <prev_pipe> receiving SIGPIPE
Packit Service 76cb02
                prev_pipe.stdout.close()
Packit Service 76cb02
            if stdout != PIPE:
Packit Service 76cb02
                # Wait until the process is finished if not in a pipe chain
Packit Service 76cb02
                rc = p.wait()
Packit Service 76cb02
                if stdout: stdout.close()
Packit Service 76cb02
Packit Service 76cb02
        return rc
Packit Service 76cb02