Пример #1
0
    def test_interrupt(self):
        """
        CAN WE CATCH A SIGINT?
        """
        p = Process("not much" ["python", "tests/resources/utils/wait_for_signal.py"])
        k = Process("killer", ["kill", "-SIGINT", p.pid])

        p.join()
Пример #2
0
def get_revision():
    """
    GET THE CURRENT GIT REVISION
    """
    proc = Process("git log", ["git", "log", "-1"])

    try:
        for line in proc.stdout:
            if line.startswith("commit "):
                return line[7:]
    finally:
        with suppress_exception:
            proc.join()
Пример #3
0
def get_branch():
    """
    GET THE CURRENT GIT BRANCH
    """
    proc = Process("git status", ["git", "status"])

    try:
        for line in proc.stdout:
            if line.startswith("On branch "):
                return line[10:]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #4
0
def app():
    global app_process

    pythonpath = str("." + os.pathsep + "vendor")
    if PY2:
        app_process = Null
    elif not app_process:
        app_process = Process("TUID app", ["python", "tuid/app.py"],
                              env={str("PYTHONPATH"): pythonpath},
                              debug=True)
        for line in app_process.stderr:
            if line.startswith(b' * Running on '):
                break
    yield
    app_process.stop()
    app_process.join(raise_on_error=False)
Пример #5
0
def get_revision():
    """
    GET THE CURRENT GIT REVISION
    """
    proc = Process("git log", ["git", "log", "-1"])

    try:
        while True:
            line = proc.stdout.pop().strip().decode('utf8')
            if not line:
                continue
            if line.startswith("commit "):
                return line[7:]
    finally:
        with suppress_exception:
            proc.join()
Пример #6
0
def get_git_revision():
    """
    GET THE CURRENT GIT REVISION
    """
    proc = Process("git log", ["git", "log", "-1"])

    try:
        while True:
            line = proc.stdout.pop().strip().decode('utf8')
            if not line:
                continue
            if line.startswith("commit "):
                return line[7:]
    finally:
        with suppress_exception:
            proc.join()
Пример #7
0
def get_branch():
    """
    GET THE CURRENT GIT BRANCH
    """
    proc = Process("git status", ["git", "status"])

    try:
        while True:
            raw_line = proc.stdout.pop()
            line = raw_line.decode('utf8').strip()
            if line.startswith("On branch "):
                return line[10:]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #8
0
def get_branch():
    """
    GET THE CURRENT GIT BRANCH
    """
    proc = Process("git status", ["git", "status"])

    try:
        while True:
            raw_line = proc.stdout.pop()
            line = raw_line.strip()
            if line.startswith("On branch "):
                return line[10:]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #9
0
def get_remote_revision(url, branch):
    """
    GET REVISION OF A REMOTE BRANCH
    """
    proc = Process("git remote revision",
                   ["git", "ls-remote", url, "refs/heads/" + branch])

    try:
        for line in proc.stdout:
            line = line.strip()
            if not line:
                continue
            return line.split("\t")[0]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #10
0
def get_remote_revision(url, branch):
    """
    GET REVISION OF A REMOTE BRANCH
    """
    proc = Process("git remote revision", ["git", "ls-remote", url, "refs/heads/" + branch])

    try:
        while True:
            raw_line = proc.stdout.pop()
            line = raw_line.strip().decode('utf8')
            if not line:
                continue
            return line.split("\t")[0]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #11
0
def get_remote_revision(url, branch):
    """
    GET REVISION OF A REMOTE BRANCH
    """
    proc = Process("git remote revision", ["git", "ls-remote", url, "refs/heads/" + branch])

    try:
        while True:
            raw_line = proc.stdout.pop()
            line = raw_line.strip().decode('utf8')
            if not line:
                continue
            return line.split("\t")[0]
    finally:
        try:
            proc.join()
        except Exception:
            pass
Пример #12
0
def app():
    global app_process

    pythonpath = str("." + os.pathsep + "vendor")
    if PY2:
        app_process = Null
    elif not app_process:
        app_process = Process(
            "TUID app",
            ["python", "tuid/app.py"],
            env={str("PYTHONPATH"): pythonpath},
            debug=True
        )
        for line in app_process.stderr:
            if line.startswith(b' * Running on '):
                break
    yield
    app_process.stop()
    app_process.join(raise_on_error=False)
Пример #13
0
class Python(object):
    def __init__(self, name, config):
        config = to_data(config)
        if config.debug.logs:
            Log.error("not allowed to configure logging on other process")

        Log.note("begin process")
        # WINDOWS REQUIRED shell, WHILE LINUX NOT
        shell = "windows" in platform.system().lower()
        self.process = Process(
            name, [PYTHON, "-u", "mo_threads" + os.sep + "python_worker.py"],
            debug=False,
            cwd=os.getcwd(),
            shell=shell)
        self.process.stdin.add(
            value2json(set_default({}, config, {"debug": {
                "trace": True
            }})))
        status = self.process.stdout.pop()
        if status != '{"out":"ok"}':
            Log.error("could not start python\n{{error|indent}}",
                      error=self.process.stderr.pop_all() + [status] +
                      self.process.stdin.pop_all())
        self.lock = Lock("wait for response from " + name)
        self.current_task = DONE
        self.current_response = None
        self.current_error = None

        self.daemon = Thread.run("", self._daemon)
        self.errors = Thread.run("", self._stderr)

    def _execute(self, command):
        with self.lock:
            self.current_task.wait()
            self.current_task = Signal()
            self.current_response = None
            self.current_error = None

            if self.process.service_stopped:
                Log.error("python is not running")
            self.process.stdin.add(value2json(command))
            (self.current_task | self.process.service_stopped).wait()

            try:
                if self.current_error:
                    Log.error("problem with process call",
                              cause=Except.new_instance(self.current_error))
                else:
                    return self.current_response
            finally:
                self.current_task = DONE
                self.current_response = None
                self.current_error = None

    def _daemon(self, please_stop):
        while not please_stop:
            line = self.process.stdout.pop(till=please_stop)
            if line == THREAD_STOP:
                break
            try:
                data = json2value(line)
                if "log" in data:
                    Log.main_log.write(*data.log)
                elif "out" in data:
                    self.current_response = data.out
                    self.current_task.go()
                elif "err" in data:
                    self.current_error = data.err
                    self.current_task.go()
            except Exception as e:
                Log.note("non-json line: {{line}}", line=line)
        DEBUG and Log.note("stdout reader is done")

    def _stderr(self, please_stop):
        while not please_stop:
            try:
                line = self.process.stderr.pop(till=please_stop)
                if line == THREAD_STOP:
                    please_stop.go()
                    break
                Log.note("Error line from {{name}}({{pid}}): {{line}}",
                         line=line,
                         name=self.process.name,
                         pid=self.process.pid)
            except Exception as e:
                Log.error("could not process line", cause=e)

    def import_module(self, module_name, var_names=None):
        if var_names is None:
            self._execute({"import": module_name})
        else:
            self._execute({"import": {"from": module_name, "vars": var_names}})

    def set(self, var_name, value):
        self._execute({"set": {var_name, value}})

    def get(self, var_name):
        return self._execute({"get": var_name})

    def execute_script(self, script):
        return self._execute({"exec": script})

    def __getattr__(self, item):
        def output(*args, **kwargs):
            if len(args):
                if kwargs.keys():
                    Log.error("Not allowed to use both args and kwargs")
                return self._execute({item: args})
            else:
                return self._execute({item: kwargs})

        return output

    def stop(self):
        self._execute({"stop": {}})
        self.process.join()
        self.daemon.stop()
        self.errors.stop()
Пример #14
0
class Python(object):

    def __init__(self, name, config):
        config = wrap(config)
        if config.debug.logs:
            Log.error("not allowed to configure logging on other process")

        self.process = Process(name, [PYTHON, "mo_threads" + os.sep + "python_worker.py"], shell=True)
        self.process.stdin.add(value2json(set_default({"debug": {"trace": True}}, config)))

        self.lock = Lock("wait for response from "+name)
        self.current_task = None
        self.current_response = None
        self.current_error = None

        self.daemon = Thread.run("", self._daemon)
        self.errors = Thread.run("", self._stderr)

    def _execute(self, command):
        with self.lock:
            if self.current_task is not None:
                self.current_task.wait()
            self.current_task = Signal()
            self.current_response = None
            self.current_error = None
        self.process.stdin.add(value2json(command))
        self.current_task.wait()
        with self.lock:
            try:
                if self.current_error:
                    Log.error("problem with process call", cause=Except.new_instance(self.current_error))
                else:
                    return self.current_response
            finally:
                self.current_task = None
                self.current_response = None
                self.current_error = None

    def _daemon(self, please_stop):
        while not please_stop:
            line = self.process.stdout.pop(till=please_stop)
            if line == THREAD_STOP:
                break
            try:
                data = json2value(line.decode('utf8'))
                if "log" in data:
                    Log.main_log.write(*data.log)
                elif "out" in data:
                    with self.lock:
                        self.current_response = data.out
                        self.current_task.go()
                elif "err" in data:
                    with self.lock:
                        self.current_error = data.err
                        self.current_task.go()
            except Exception:
                Log.note("non-json line: {{line}}", line=line)
        DEBUG and Log.note("stdout reader is done")

    def _stderr(self, please_stop):
        while not please_stop:
            try:
                line = self.process.stderr.pop(till=please_stop)
                if line == THREAD_STOP:
                    please_stop.go()
                    break
                Log.note("Error line from {{name}}({{pid}}): {{line}}", line=line, name=self.process.name, pid=self.process.pid)
            except Exception as e:
                Log.error("could not process line", cause=e)

    def import_module(self, module_name, var_names=None):
        if var_names is None:
            self._execute({"import": module_name})
        else:
            self._execute({"import": {"from": module_name, "vars": var_names}})

    def set(self, var_name, value):
        self._execute({"set": {var_name, value}})

    def get(self, var_name):
        return self._execute({"get": var_name})

    def execute_script(self, script):
        return self._execute({"exec": script})

    def __getattr__(self, item):
        def output(*args, **kwargs):
            if len(args):
                if len(kwargs.keys()):
                    Log.error("Not allowed to use both args and kwargs")
                return self._execute({item: args})
            else:
                return self._execute({item: kwargs})
        return output

    def stop(self):
        self._execute({"stop": {}})
        self.process.join()
        self.daemon.stop()
        self.errors.stop()
Пример #15
0
class Schedule(object):
    @override
    def __init__(
        self,
        interval,  # TIME INTERVAL BETWEEN RUNS
        starting,  # THE TIME TO START THE INTERVAL COUNT
        max_runtime=MAX_RUNTIME,  # LIMIT HOW LONG THE PROCESS IS ALIVE
        wait_for_shutdown=WAIT_FOR_SHUTDOWN,  # LIMIT PAITENCE WHEN ASKING FOR SHUTDOWN, THEN SEND KILL
        process=None,
    ):
        self.duration = Duration(interval)
        self.starting = coalesce(Date(starting), Date.now())
        self.max_runtime = Duration(max_runtime)
        self.wait_for_shutdown = Duration(wait_for_shutdown)
        # Process parameters
        self.process = process

        # STATE
        self.last_started = None
        self.last_finished = None
        self.run_count = 0
        self.fail_count = 0
        self.current = None
        self.terminator = None  # SIGNAL TO KILL THE PROCESS
        self.next_run = self._next_run()
        self.next = Till(till=self.next_run)
        self.next_run.then(self.run)

    def _next_run_time(self):
        """
        :return: return signal for next
        """

        interval = mo_math.floor((Date.now() - self.starting) / self.duration)
        next_time = self.starting + (interval * self.duration)
        return next_time

    def run(self):
        self.last_started = Date.now()
        self.run_count += 1
        self.current = Process(**self.process)
        self.terminator = Till(seconds=self.max_runtime.seconds)
        self.terminator.then(self.killer)
        self.current.service_stopped.then(self.done)

    def killer(self, please_stop):
        self.current.stop()
        (
            please_stop
            | self.current.service_stopped()
            | Till(seconds=self.wait_for_shutdown.seconds)
        ).wait()
        if not self.current.service_stopped:
            self.fail_count += 1
            self.current.kill()
            self.current.join()

    def done(self):
        self.last_finished = Date.now()
        self.terminator.remove_go(self.killer)
        self.terminator = None
        self.current = None
        self.next_run = self._next_run_time()
        self.next = Till(till=self.next_run.unix)
        self.next.then(self.run)

    def status(self):
        if self.current is None:
            status = "never started"
        elif not self.current.service_stopped:
            status = "running"
        elif self.current.returncode == 0:
            status = "done"
        else:
            status = "failed " + text(self.current.returncode)

        return Data(
            name=self.name,
            next_run=self.next_run,
            last_started=self.last_started,
            last_finished=self.last_finished,
            status=status,
        )