Example #1
0
def validate_run(stdout: multiprocessing.Pipe, stderr: multiprocessing.Pipe,
                 module_path: str):
    """
    Run the example from ``module_path`` isolated in a process.

    This fakes the subfolder execution of the example scripts by loading them into the TOP_DIRECTORY path and
    replaces all of the ``from pyipv8`` imports in the example scripts.
    """
    os.dup2(stdout.fileno(),
            1)  # Forward all stdout (1) calls to the stdout argument
    os.dup2(stderr.fileno(),
            2)  # Forward all stderr (2) calls to the stdout argument

    sys.path.insert(0, TOP_DIRECTORY)

    with open(module_path, 'r') as module_file_h:
        module_contents = ""
        line = module_file_h.readline()
        while line:
            if line.startswith("from pyipv8."):
                line = "from " + line[len("from pyipv8."):]
            module_contents += line
            line = module_file_h.readline()

    exec(
        compile(module_contents,
                module_path,
                'exec',
                dont_inherit=True,
                optimize=0), {})  # pylint: disable=W0122
Example #2
0
 def __init__(self):
     r, w = Pipe(duplex=False)
     _set_non_blocking(r.fileno())
     _set_non_blocking(w.fileno())
     close_on_exec(r.fileno())
     close_on_exec(w.fileno())
     self._writer = w
     self._reader = r
Example #3
0
 def __init__(self):
     r, w = Pipe(duplex=False)
     _set_non_blocking(r.fileno())
     _set_non_blocking(w.fileno())
     close_on_exec(r.fileno())
     close_on_exec(w.fileno())
     self._writer = w
     self._reader = r
Example #4
0
def run_forked(suite):
    keep_alive_parent_end, keep_alive_child_end = Pipe(duplex=False)
    result_parent_end, result_child_end = Pipe(duplex=False)

    child = Process(target=test_runner_wrapper,
                    args=(suite, keep_alive_child_end, result_child_end))
    child.start()
    last_test_temp_dir = None
    last_test_vpp_binary = None
    last_test = None
    result = None
    while result is None:
        readable = select.select([
            keep_alive_parent_end.fileno(),
            result_parent_end.fileno(),
        ], [], [], test_timeout)[0]
        if result_parent_end.fileno() in readable:
            result = result_parent_end.recv()
        elif keep_alive_parent_end.fileno() in readable:
            while keep_alive_parent_end.poll():
                last_test, last_test_vpp_binary,\
                    last_test_temp_dir, vpp_pid = keep_alive_parent_end.recv()
        else:
            global_logger.critical("Timeout while waiting for child test "
                                   "runner process (last test running was "
                                   "`%s' in `%s')!" %
                                   (last_test, last_test_temp_dir))
            failed_dir = os.getenv('VPP_TEST_FAILED_DIR')
            lttd = last_test_temp_dir.split("/")[-1]
            link_path = '%s%s-FAILED' % (failed_dir, lttd)
            global_logger.error("Creating a link to the failed " +
                                "test: %s -> %s" % (link_path, lttd))
            os.symlink(last_test_temp_dir, link_path)
            api_post_mortem_path = "/tmp/api_post_mortem.%d" % vpp_pid
            if os.path.isfile(api_post_mortem_path):
                global_logger.error("Copying api_post_mortem.%d to %s" %
                                    (vpp_pid, last_test_temp_dir))
                shutil.copy2(api_post_mortem_path, last_test_temp_dir)
            if last_test_temp_dir and last_test_vpp_binary:
                core_path = "%s/core" % last_test_temp_dir
                if os.path.isfile(core_path):
                    global_logger.error("Core-file exists in test temporary "
                                        "directory: %s!" % core_path)
                    if d and d.lower() == "core":
                        spawn_gdb(last_test_vpp_binary, core_path,
                                  global_logger)
            child.terminate()
            result = -1
    keep_alive_parent_end.close()
    result_parent_end.close()
    return result
def create_worker(env, priority='normal', cwd=None, func='main'):
    env = dict(env)
    a, b = Pipe()
    with a:
        env.update({
            'CALIBRE_WORKER_FD':
            str(a.fileno()),
            'CALIBRE_SIMPLE_WORKER':
            environ_item('calibre.utils.ipc.simple_worker:%s' % func),
        })

        w = Worker(env)
        w(cwd=cwd, priority=priority, pass_fds=(a.fileno(), ))
    return b, w
Example #6
0
class ProcessApplication(Application):
    """Run application class in subprocess."""

    def __init__(self, reaktor, target, name=''):
        Application.__init__(self, None, name)
        self.target = target
        self._reaktor = reaktor
        self._process = None
        self.parent = None
        self.child = None
        self.transport = None
        self.runner = None

    def start(self):
        signal.signal(signal.SIGCHLD, self._sigchld)
        self.parent, self.child = Pipe(duplex=True)
        logging.debug("parent conn %d, child %d",
                      self.parent.fileno(), self.child.fileno())
        self.transport = ConnectedTransport(self._reaktor, self.parent, self)
        self.runner = _Subprocess(self.target, self.child, self.config)
        self._process = Process(target=self.runner.run)
        self._process.start()

    def _close(self, timeout):
        self._process.join(timeout)
        if self.transport is not None:
            # this closes also parent channel
            self.transport.close()
            self.transport.del_channel()
        self.child = self.parent = self.transport = None

    def _sigchld(self, signum, frame):
        self._close(0.5)

    def stop(self):
        self._process.terminate()
        self._close(2.0)

    def send(self, data):
        """Send data to application."""
        self.parent.send(data)

    def recv(self, data):
        """Handle data received from subprocess application."""
        if isinstance(data, Exception):
            self.log.error("Subprocess exception: %s", str(data))
            raise data
        self.received(data)

    def event_readable(self, transport):
        assert(transport == self.transport)
        data = self.transport.socket.recv()
        self.log.debug("received from app: %s", str(data))
        if data is not None:
            self.recv(data)

    def event_error(self, transport):
        typ, ex, tb = sys.exc_info()
        if typ != KeyboardInterrupt:
            self.log.debug("process: %s", str(ex))
Example #7
0
class HTTPServerProcess(QObject):
    def __init__(self, handler, parent=None) -> None:
        super().__init__(parent)
        self.parent_conn, self.child_conn = Pipe()

        self.notifier = QSocketNotifier(self.parent_conn.fileno(),
                                        QSocketNotifier.Read, self)
        self.notifier.activated.connect(self.dataReady)

        self.p = Process(target=handler, args=(self.child_conn, ))

        def _on_quit():
            print("> REQUESTING HTTPD SHUTDOWN...")
            self.parent_conn.send("http_server_shutdown")
            # block current process until the child process ends correctly, then close the child
            self.p.join()
            self.p.close()

        qApp.aboutToQuit.connect(
            _on_quit)  # terminate children processes before app exit
        self.p.start()

    dataReady = PS2Signal()

    def read(self):
        return self.parent_conn.recv() if self.parent_conn.poll() else None
class ConsoleProxy(object):
    def __init__(self):
        self._read, self._write = Pipe(duplex=True)

    def fileno(self):
        return self._read.fileno()

    def read(self):
        data = self._read.recv()
        if data["type"] == "completer":
            result = command_root.match(data["line"], data["hints"])
        elif data["type"] == "parser":
            try:
                result = command_root.parse(data["line"])
            except Command.NotFound as e:
                if str(e) != "":
                    result = str(e)
                else:
                    result = "No such command '{:s}'".format(data["line"])
            except Command.SyntaxError as e:
                result = str(e)
        else:
            result = ""

        self._read.send(result)

    def completer(self, line, hints):
        self._write.send({"type" : "completer", "line" : line, "hints" : hints})
        return self._write.recv()

    def parser(self, line):
        self._write.send({"type" : "parser", "line" : line})
        return self._write.recv()
Example #9
0
class ProcessApplication(Application):
    """Run application class in subprocess."""
    def __init__(self, reaktor, target, name=''):
        Application.__init__(self, None, name)
        self.target = target
        self._reaktor = reaktor
        self._process = None
        self.parent = None
        self.child = None
        self.transport = None
        self.runner = None

    def start(self):
        signal.signal(signal.SIGCHLD, self._sigchld)
        self.parent, self.child = Pipe(duplex=True)
        logging.debug("parent conn %d, child %d", self.parent.fileno(),
                      self.child.fileno())
        self.transport = ConnectedTransport(self._reaktor, self.parent, self)
        self.runner = _Subprocess(self.target, self.child, self.config)
        self._process = Process(target=self.runner.run)
        self._process.start()

    def _close(self, timeout):
        self._process.join(timeout)
        if self.transport is not None:
            # this closes also parent channel
            self.transport.close()
            self.transport.del_channel()
        self.child = self.parent = self.transport = None

    def _sigchld(self, signum, frame):
        self._close(0.5)

    def stop(self):
        self._process.terminate()
        self._close(2.0)

    def send(self, data):
        """Send data to application."""
        self.parent.send(data)

    def recv(self, data):
        """Handle data received from subprocess application."""
        if isinstance(data, Exception):
            self.log.error("Subprocess exception: %s", str(data))
            raise data
        self.received(data)

    def event_readable(self, transport):
        assert (transport == self.transport)
        data = self.transport.socket.recv()
        self.log.debug("received from app: %s", str(data))
        if data is not None:
            self.recv(data)

    def event_error(self, transport):
        typ, ex, tb = sys.exc_info()
        if typ != KeyboardInterrupt:
            self.log.debug("process: %s", str(ex))
Example #10
0
    def do_launch(self, gui, redirect_output, rfile, job_name=None):
        a, b = Pipe()
        with a:
            env = {
                'CALIBRE_WORKER_FD': str(a.fileno()),
                'CALIBRE_WORKER_RESULT': environ_item(as_hex_unicode(rfile))
            }
            w = Worker(env, gui=gui, job_name=job_name)

            try:
                w(pass_fds=(a.fileno(), ), redirect_output=redirect_output)
            except BaseException:
                try:
                    w.kill()
                except:
                    pass
                b.close()
                import traceback
                return traceback.format_exc()
        return ConnectedWorker(w, b, rfile)
Example #11
0
def main():
    """ Main function, gets arguments from sys.argv and starts chat and listen
        thread """
    parser = ArgumentParser(description='Chat program')
    parser.add_argument('-l', '--local-port', default=12345, type=int)
    parser.add_argument('-n', '--name', default='apa', help='Your name')
    args = parser.parse_args()
    host = Address(socket.gethostname(), args.local_port)

    new_chat_pipe_out, new_chat_pipe_in = Pipe(False)
    state = State(args.name, host)
    input_control = InputControl(args.name, host, state)
    l_thread = GenericThread(listen_thread, host, state, new_chat_pipe_in)
    l_thread.start()

    print(">", end=" ")
    sys.stdout.flush()
    while True:
        try:
            input_ready, _, _ = select.select([sys.stdin,
                                              new_chat_pipe_out.fileno()],
                                              [], [], 0)
            if sys.stdin in input_ready:
                # Command from command line
                line = sys.stdin.readline()
                if line:
                    input_control.handle_input(line)
                else:
                    # Shutdown on EOF
                    input_control.shutdown()
            if new_chat_pipe_out.fileno() in input_ready:
                # Got message from friend, but chat is not open
                friend_name = new_chat_pipe_out.recv()
                state.connect_to(friend_name)
            # Check if any chat has been closed
            state.check_closed_chat()
            time.sleep(0.1)

        except (EOFError, KeyboardInterrupt):
            state.shutdown()
            l_thread.terminate()
Example #12
0
def run_forked(suite):
    keep_alive_parent_end, keep_alive_child_end = Pipe(duplex=False)
    result_parent_end, result_child_end = Pipe(duplex=False)

    child = Process(target=test_runner_wrapper,
                    args=(suite, keep_alive_child_end, result_child_end))
    child.start()
    last_test_temp_dir = None
    last_test_vpp_binary = None
    last_test = None
    result = None
    while result is None:
        readable = select.select([keep_alive_parent_end.fileno(),
                                  result_parent_end.fileno(),
                                  ],
                                 [], [], test_timeout)[0]
        if result_parent_end.fileno() in readable:
            result = result_parent_end.recv()
        elif keep_alive_parent_end.fileno() in readable:
            while keep_alive_parent_end.poll():
                last_test, last_test_vpp_binary, last_test_temp_dir =\
                    keep_alive_parent_end.recv()
        else:
            global_logger.critical("Timeout while waiting for child test "
                                   "runner process (last test running was "
                                   "`%s' in `%s')!" %
                                   (last_test, last_test_temp_dir))
            if last_test_temp_dir and last_test_vpp_binary:
                core_path = "%s/core" % last_test_temp_dir
                if os.path.isfile(core_path):
                    global_logger.error("Core-file exists in test temporary "
                                        "directory: %s!" % core_path)
                    if d and d.lower() == "core":
                        spawn_gdb(last_test_vpp_binary, core_path,
                                  global_logger)
            child.terminate()
            result = -1
    keep_alive_parent_end.close()
    result_parent_end.close()
    return result
Example #13
0
def start_streaming_search():
    global subprocess_to_main1, subprocess_to_main2, search_subprocess
    subprocess_to_main1, subprocess_to_main2 = Pipe(duplex=False)
    search_subprocess = Process(target=streaming_search,
                                kwargs={
                                    "subprocess_to_main": subprocess_to_main2,
                                    "search_targets": search_targets,
                                    "filter_level": filter_level,
                                    "english_only": english_only
                                })
    search_subprocess.start()
    IOLoop.instance().add_handler(
        subprocess_to_main1.fileno(),
        partial(on_streaming_search_msg, subprocess_to_main1), IOLoop.READ)
Example #14
0
def start_streaming_search():
    global subprocess_to_main1, subprocess_to_main2, search_subprocess
    subprocess_to_main1, subprocess_to_main2 = Pipe(duplex=False)
    search_subprocess = Process(target=streaming_search, kwargs={
        "subprocess_to_main": subprocess_to_main2,
        "search_targets": search_targets,
        "filter_level": filter_level,
        "english_only": english_only
    })
    search_subprocess.start()
    IOLoop.instance().add_handler(
        subprocess_to_main1.fileno(),
        partial(on_streaming_search_msg, subprocess_to_main1),
        IOLoop.READ)
Example #15
0
class ThreadConnector:
    def connect(self, remote):
        self.pipe, remote.pipe = Pipe()
    def close(self):
        self.pipe.close()
    def fileno(self):
        return self.pipe.fileno()
    def write(self, obj):
        self.pipe.send(obj)
    def read(self):
        return self.pipe.recv()
    def poll(self):
        return self.pipe.poll()
    def wait_next_event(self):
        # we implement a loop in order to make this wait
        # interruptible (every WAIT_MAX seconds)
        while not self.pipe.poll(WAIT_MAX):
            pass
    def _make_tab(self, uri: str = 'about:blank', switch_to: bool = False):
        """ Make a tab.

        """

        socket_id, child = self._add_tab(switch_to)

        main_pipe, child_pipe = Pipe()

        com_dict = Manager().dict({socket_id: child_pipe})

        child['com-tup'] = (main_pipe, com_dict)
        child['pid'] = 0
        child['uri'] = uri
        self._windows[socket_id] = child

        self._glib.io_add_watch(main_pipe.fileno(), self._glib.IO_IN,
                                self._callback, child)

        return com_dict
Example #17
0
class EvThread(Thread):
    def __init__(self, manager, name):
        Thread.__init__(self, name=name)
        self.ev_loop = EventLoop()
        self.pipe_in, self.pipe_out = Pipe()
        self.ev_loop.register_listener(self)
        manager.register_thread(self)

    # mimic an event loop
    def __getattr__(self, attr):
        return getattr(self.ev_loop, attr)

    def run(self):
        try:
            with AutoCleaner(self):
                self.prepare()
                self.ev_loop.loop()
        except DownwardPropagatedException:
            print(self.name + ' stopped because of propagated exception.')
        except BaseException as e:
            try:
                self.pipe_in.send(e)  # propagate upward
            except BaseException as issue:
                self.pipe_in.send(Exception(str(e)))
            raise

    def fileno(self):
        return self.pipe_in.fileno()

    def forward_exception(self, e):
        self.pipe_out.send(e)

    def handle_event(self, ts):
        self.down_exception = self.pipe_in.recv()
        raise DownwardPropagatedException

    def prepare(self):
        pass  # optionally override in subclass

    def cleanup(self):
        pass  # optionally override in subclass
Example #18
0
    def __init__(self, device: Device):
        super(Control, self).__init__()
        self.device = device
        label = Gtk.Label(LABEL_START + 'CONTROL' + LABEL_END, **LABEL_PROPS)

        ctrl_btn = Gtk.Button('READY')
        pull_btn = Gtk.Button('PULL')

        self.auto_pull = Gtk.CheckButton()
        auto_pull_lbl = Gtk.Label('Auto pull')

        ctrl_btn.connect('pressed', self.ctrl_begin_callback)
        pull_btn.connect('pressed', self.push_wrap)

        self.attach(label, 0, 0, 2, 1)
        self.attach(ctrl_btn, 0, 1, 2, 1)
        self.attach(auto_pull_lbl, 0, 2, 1, 1)
        self.attach(self.auto_pull, 1, 2, 1, 1)

        self.attach(Gtk.Label(''), 0, 3, 2, 1)
        self.attach(pull_btn, 0, 4, 2, 1)

        # Glib workaround begin
        # https://stackoverflow.com/questions/13518452/
        parent_conn, self.child_conn = Pipe(
            duplex=False)  # Pipe to pump the label data through

        self.child_conn.send("<span color='green'>READY</span>")

        def read_data(source, condition):
            """
            watches pipe and when data changes, changes the label
            """
            assert parent_conn.poll()
            i = parent_conn.recv()
            for child in ctrl_btn.get_children():
                child.set_label(i)
                child.set_use_markup(True)
            return True  # continue reading

        GObject.io_add_watch(parent_conn.fileno(), GObject.IO_IN, read_data)
def run(sim, idx):
    path = "/home/ubb/Documents/PersonalProject/VrController/sim_recorder/data/"
    r, w = Pipe()
    q = Queue()
    reader = os.fdopen(r.fileno(), 'r')
    interrupt_event = Event()
    procs = generate_procs(sim.name, sim.commands, r, w, q, interrupt_event,
                           idx)
    time.sleep(1)
    pids = start_proces(sim.delays, procs, q)
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(sim.timeout)
    start_time = time.time()
    with open(path+f"{sim.name}/log/{idx}.txt", "w") as f,\
            open(path+f"{sim.name}/run.txt", "a") as out:
        try:
            while True:
                text = reader.readline()
                f.write(text)
                if "Task completed Succesfully" in text or "ODE INTERNAL ERROR" in text:
                    print(
                        f"Completed for {idx} in {time.time() - start_time }")
                    out.write(
                        f"Completed for {idx} in {time.time() - start_time }\n"
                    )
                    signal.alarm(0)
                    kill_proc_tree(pids, procs, interrupt_event)
                    return 1, 0
                if "Cube is not in bound" in text:
                    print(f"Failed for {idx} in {time.time() - start_time }")
                    out.write(
                        f"Failed for {idx} in {time.time() - start_time }\n")
                    signal.alarm(0)
                    kill_proc_tree(pids, procs, interrupt_event)
                    return 0, 1
        except:
            print(f"Timeout for {idx}")
            out.write(f"Timeout for {idx}\n")
            f.write("Timeout")
            kill_proc_tree(pids, procs, interrupt_event)
            return 0, 0
Example #20
0
def main():
    server_fd,client_fd = Pipe()
    client = Process(target = client_do,args = (server_fd,client_fd))
    client.start()
    client_fd.close()
    print("Service Start")
    while True:
        _,_,_ = select.select([server_fd.fileno()],[],[])
        url,email = server_fd.recv()
        filename = "/tmp/%s.gif"%random_str(10)
        pid = os.fork()
        if pid == 0:
            try:
                change_user(EXEC_USER)
                start_chrome(url,filename)
                send_vedio(filename,email)
            except Exception as e:
                traceback.print_exc(file=sys.stdout)
                print("Server Err:", e)
            os._exit(0)
        else:
            os.waitpid(pid,0)
Example #21
0
class DaemonService(BaseService):
    """
    In charge to receive messages and send responses to subscribed clients
    """
    def __init__(self, name, config):
        super(DaemonService, self).__init__(name, config)
        self.proc = Process(target=self.main)
        self.proc.daemon = True
        self.parent_end, self.child_end = Pipe()
        self.listen_fileno = self.parent_end.fileno()
    def listen (self, timeout=None):
        if not self.child_end.poll(timeout):
            return
        msg = self.child_end.recv()
        self.exec_action(msg)
    def add_event(self, msg):
        self.logger.debug("Piping message: %s" % msg)
        self.parent_end.send(msg)
    def send_action(self, msg):
        self.child_end.send(msg)
    def recv_action(self):
        return self.parent_end.recv()
Example #22
0
class self_pipe:
    def __init__(self):
        self.__fd_read, self.__fd_send = Pipe()
        pass

    def __del__(self):
        self.__fd_read.close()
        self.__fd_send.close()

    def get_read_fd(self):
        return self.__fd_read.fileno()

    def get_write_fd(self):
        return self.__fd_send.fileno()

    def notify(self):
        self.__fd_send.send('a')
        pass

    def clr_buffer(self):
        data = self.__fd_read.recv()
        # print(data)
        pass
Example #23
0
def main():

    poller = select.poll()

    logFile = open('log_firewall_events.txt', 'w')
    # Create a TCP/IP socket for events besides flow tracker.
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setblocking(0)

    # Bind the socket to the port
    server_address = ('localhost', 10000)
    print('starting up on %s port %s' % server_address)
    server.bind(server_address)

    # Listen for incoming connections
    server.listen(5)

    # Create a TCP/IP socket to send data to local
    localSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    localSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # Bind the socket to the port
    local_address = ('localhost', 10001)
    print('starting up on %s port %s' % local_address)
    localSocket.bind(local_address)

    # Listen for incoming connections
    localSocket.listen(1)

    # Wait for local verifier to connect. Comment next two lines when testing with sample data
    local_connection, local_client_address = localSocket.accept()
    print('new local verifier connection from', local_client_address)

    # Create stdin pipe
    pipeIn = sys.stdin

    # Commonly used flag setes
    READ_ONLY = select.POLLIN
    READ_WRITE = READ_ONLY | select.POLLOUT

    # Create output pipe
    pipe_recv, pipe_send = Pipe(duplex=False)

    #
    fd_to_object = {
        pipeIn.fileno(): pipeIn,
        server.fileno(): server,
        pipe_recv.fileno(): pipe_recv,
        pipe_send.fileno(): pipe_send
    }

    # Make input stream non-blocking
    old_flags = fcntl.fcntl(pipeIn.fileno(), fcntl.F_GETFL)
    fcntl.fcntl(pipeIn.fileno(), fcntl.F_SETFL, old_flags | os.O_NONBLOCK)

    poller.register(pipeIn)
    poller.register(server, READ_ONLY)
    poller.register(pipe_recv, READ_ONLY)
    poller.register(pipe_send, READ_ONLY)
    count = 0

    while True:
        # print("waiting on poll")
        events = poller.poll()
        # print("poll output", events)

        for fd, flag in events:
            # print("fd:", fd, " flag:", flag )

            currentObject = fd_to_object[fd]

            if currentObject is pipeIn and (flag != select.POLLHUP):
                allOut = currentObject.read()
                for line in allOut.splitlines():
                    # print("received line: ", line)
                    logFile.write(
                        str(datetime.now().strftime("%H:%M:%S.%f")) + ',' +
                        str(count) + '\n')
                    count += 1
                    pipe_send.send(line)
            elif currentObject is pipeIn and (
                    flag == select.POLLHUP) and len(events) == 1:

                local_connection.close()
                for key, item in fd_to_object.items():
                    poller.unregister(item)
                    if isinstance(item, socket.socket):
                        item.close()
                print("input closed. terminating")
                sys.exit()

            elif currentObject is pipe_recv:
                data = currentObject.recv()
                # print("data:", data)
                for line in data.splitlines():
                    # print("data received: ", line)
                    if "block" in line:
                        # print("Sending to local: ", line )
                        local_connection.send(line.encode())
                    else:
                        tempOut = parse_line(line)
                        # print("Sending to local: ", tempOut)
                        # print([int(x) for x in tempOut])
                        # print("Number of bytes: ", len(tempOut))

                        local_connection.send(tempOut)

            elif flag & (select.POLLIN | select.POLLPRI):

                if currentObject is server:
                    # A "readable" server socket is ready to accept a connection
                    connection, client_address = currentObject.accept()
                    print('new connection from', client_address)
                    connection.setblocking(0)
                    fd_to_object[connection.fileno()] = connection
                    poller.register(connection, READ_ONLY)
                    print("connection from block adder")
                else:
                    data = currentObject.recv(1024)
                    if data:
                        # A readable client socket has data
                        print('received "%s" from %s' %
                              (data, currentObject.getpeername()))
                        pipe_send.send(data)

                    else:
                        # Interpret empty result as closed connection
                        print('closing', currentObject.getpeername(),
                              'after reading no data')
                        # Stop listening for input on the connection
                        poller.unregister(currentObject)
                        currentObject.close()
            elif isinstance(currentObject,
                            socket.socket) and flag & select.POLLHUP:
                # Client hung up
                print('closing', currentObject.getpeername(),
                      'after receiving HUP')
                # Stop listening for input on the connection
                poller.unregister(currentObject)
                currentObject.close()

            elif isinstance(currentObject,
                            socket.socket) and flag & select.POLLERR:
                print('handling exceptional condition for',
                      currentObject.getpeername())
                # Stop listening for input on the connection
                poller.unregister(currentObject)
                currentObject.close()

            elif currentObject is pipe_send:
                print("Error in pipe_send")
                sys.exit(1)
            else:
                print("Unknown context")
                sys.exit(2)
Example #24
0
class SoundAnalyzer(object):

    class Bin(object):
        def __init__(self, fps):
            self._fps = fps
            self._level = 0
            self._prevlevel = 0
            self._avgflux = filter.RMA(fps * 2.5)
            self._avgflux_rect = filter.RMA(fps * 2.5)
            self._flux_thres = filter.MMF(fps * 5)
            self._attack = False
            self._in_transient = False
            self._transient = 0.0
            self._transient_period = filter.RMA(fps * 2)
            self._transient_period.add(0.25)
            self._ts = time.time()

        @property
        def level(self):
            return self._level

        @level.setter
        def level(self, value):
            now = time.time()
            dt = now - self._ts
            self._ts = now

            self._prevlevel = self._level
            # Approximated rolling average
            self._level = (self._level / 2.0) + (value / 2.0)

            # Update spectral flux value
            flux = self._level - self._prevlevel
            self._avgflux.add(abs(flux))

            # Onset/transient calculation
            in_attack = self._level >= self._prevlevel
            onset = flux - self._avgflux_rect.value() >= self._flux_thres.value()

            if not self._in_transient:
                if onset:
                    self._attack = True
                    self._in_transient = True
                    self._transient = 1.0
                    self._onset_ts = now
                    self._attack_vector = [self._level]
                    self._transient_level = self._level
            else:
                x = 1.0 / (self._transient_period.value() / dt)
                self._transient -= x

                if self._attack:
                    if not in_attack:
                        self._transient_level = \
                            np.mean(self._attack_vector) * 0.75
                    else:
                        self._attack_vector.append(self._level)
                    self._attack = in_attack
                else:
                    if self._level < self._transient_level:
                        if self._transient <= 0.0:
                            self._transient = 0.0
                            self._in_transient = False
                            transient = min(1.0, now - self._onset_ts)
                            self._transient_period.add(transient)
                        self._transient /= 2

                    if self._transient <= -4.0:
                        self._transient = 0.0
                        self._in_transient = False
                        self._transient_period.add(self._transient_period.value())

            self._avgflux_rect.add(max(0.0, flux))
            if flux > 0:
                self._flux_thres.add(flux)

        @property
        def flux(self):
            return self._avgflux.value()

        @property
        def transient(self):
            return max(0.0, self._transient)

    def __init__(self, sample, fps):
        self._fps = fps
        chunk = int(sample / fps)

        self._chunk = chunk
        self._sample = sample
        self._channels = 1
        self._sample_width = 16

        bins = []
        freq = sample
        # Split sample rate into bins with an exponential decay
        # and 0-156 selected as the smallest band.  We calculate
        # the mean power over these bins.
        scale = 2
        freq = freq / 2
        while freq > 156:
            prev_freq = freq
            while True:
                freq = freq / scale
                # Pre-calculate offset into power array
                prev_power_idx = scale * chunk * prev_freq / sample
                power_idx = scale * chunk * freq / sample
                if (prev_power_idx - power_idx) >= 1:
                    break
            bins.insert(0, [power_idx, prev_power_idx])

        bins.insert(0, [0, (scale * chunk * freq / sample)])
        self._bins = bins

        # Calculate EQ weights
        # Range from 2^0 to 2^6 (64) stretched over the number of bins
        self._eq = np.power(2, np.linspace(0, 6, len(self._bins)))

        self._running = Value('i', 0)
        self._pipe, pipe = Pipe(duplex=False)

        self._p = Process(target=self._run, args=(self._running, pipe))
        self._p.daemon = True
        self._p.start()
        pipe.close()

    def close(self):
        self._running.value = -1
        self._p.terminate()
        self._p.join()

    def start(self):
        self._running.value = 1

    def stop(self):
        self._running.value = 0

    def fileno(self):
        return self._pipe.fileno()

    def _run(self, running, pipe):
        self._pipe.close()
        self._pipe = pipe
        signal.signal(signal.SIGINT, signal.SIG_IGN)

        while running.value >= 0:
            if running.value == 1:
                self._analyze(running, pipe)
            else:
                time.sleep(0.1)

    def _analyze(self, running, pipe):
        pa = pyaudio.PyAudio()
        sample_fmt = pa.get_format_from_width(self._sample_width / 8)
        input = pa.open(format=sample_fmt, input=True,
            channels=self._channels, rate=self._sample,
            frames_per_buffer=self._chunk)

        sample_size = self._sample_width / 8
        frame_len = self._chunk * sample_size * self._channels

        if sample_size == 1:
            data_type = 'b'
            unpack_fmt = "%db" % int(frame_len)
        elif sample_size == 2:
            data_type = 'h'
            unpack_fmt = "%dh" % int(frame_len / 2)

        spectrum = [0] * len(self._bins)

        bin_per_band = (len(self._bins) - 1) / 2
        bass_e = 1
        mid_e = bass_e + bin_per_band

        bass = SoundAnalyzer.Bin(self._fps)
        mid = SoundAnalyzer.Bin(self._fps)
        tre = SoundAnalyzer.Bin(self._fps)

        silence_thres = 0.05

        scale_avg = filter.RMA(self._fps * 30)
        scale_avg.add(1)
        scale_raw = 1
        scale = scale_raw
        scale_lock = None

        avg_loudness = 0
        prev_loudness_diff = 0
        loudness_ack = 0

        start = time.time()
        while running.value == 1:
            try:
                frame = input.read(self._chunk)
            except:
                continue

            cur = time.time()
            dt = cur - start
            start = cur

            # Convert raw to numpy array
            frame = unpack(unpack_fmt, frame)
            frame = np.array(frame, dtype=data_type)

            # Run numpy real FFT
            fourier = np.fft.rfft(frame)
            power = np.abs(fourier)

            i = 0
            for bin in self._bins:
                s,e = bin
                spectrum[i] = np.mean(power[s:e])
                i = i + 1

            spectrum = np.multiply(spectrum, self._eq)
            spectrum = np.divide(spectrum, scale)
            spectrum = spectrum.clip(0.0, 1.0)

            bass.level = np.mean(spectrum[0:bass_e])
            mid.level = np.mean(spectrum[bass_e:mid_e])
            tre.level = np.mean(spectrum[mid_e:])

            silence = bass.level <= silence_thres and \
                mid.level <= silence_thres and \
                tre.level <= silence_thres

            loudness = (bass.level + mid.level +  tre.level) / 3
            avg_loudness = (0.75 * avg_loudness) + (1.0 - 0.75) * loudness

            # Calculate the scaling factor with a PID-based algorithm with
            # an approximated moving average of 0.25 as target loudness level.
            # The purpose of this is to have a rapid increase of the scaling
            # factor to a useful value but then to keep it at a stable value
            # versus the flux of the input loudness.
            if not silence:
                diff = avg_loudness - 0.25
                loudness_ack = loudness_ack + (diff * dt)
                loudness_d = (diff - prev_loudness_diff) / dt
                output = 0.5*diff + 0.001*loudness_ack + 0.0001*loudness_d
                prev_loudness_diff = diff
                factor = 1 + output

                scale_raw = scale * factor

                # Don't update the scale value at "small enough" diffs
                if abs(diff) <= 0.1:
                    scale_lock = True
                # Use a RMA average filter as scaling for
                # "almost small" enough values.
                elif abs(diff) <= 0.25:
                    scale_lock = False
                # Otherwise use raw scale factor directly from PID
                else:
                    scale_lock = None

                if scale_lock == False:
                    scale_avg.add(scale_raw)
                    scale = scale_avg.value()
                elif scale_lock == None:
                    scale_avg.add(scale_raw)
                    scale = scale_raw

            pipe.send({"bins" : {
                    "bass" : {
                        "level" : bass.level,
                        "flux" : bass.flux,
                        "transient" : bass.transient
                    },
                    "mid" : {
                        "level" : mid.level,
                        "flux" : mid.flux,
                        "transient" : mid.transient
                    },
                    "tre" : {
                        "level" : tre.level,
                        "flux" : tre.flux,
                        "transient" : tre.transient
                    },
                }, "silence": silence, "spectrum" : spectrum})

        input.stop_stream()
        input.close()
        pa.terminate()

    def data(self, drop=True):
        data = self._pipe.recv()
        while drop and self._pipe.poll():
            data = self._pipe.recv()
        return data
Example #25
0
def run_forked(suite):
    keep_alive_parent_end, keep_alive_child_end = Pipe(duplex=False)
    result_parent_end, result_child_end = Pipe(duplex=False)
    failed_parent_end, failed_child_end = Pipe(duplex=False)

    child = Process(target=test_runner_wrapper,
                    args=(suite, keep_alive_child_end, result_child_end,
                          failed_child_end))
    child.start()
    last_test_temp_dir = None
    last_test_vpp_binary = None
    last_test = None
    result = None
    failed = set()
    last_heard = time.time()
    core_detected_at = None
    debug_core = os.getenv("DEBUG", "").lower() == "core"
    while True:
        readable = select.select([
            keep_alive_parent_end.fileno(),
            result_parent_end.fileno(),
            failed_parent_end.fileno(),
        ], [], [], 1)[0]
        if result_parent_end.fileno() in readable:
            result = result_parent_end.recv()
            break
        if keep_alive_parent_end.fileno() in readable:
            while keep_alive_parent_end.poll():
                last_test, last_test_vpp_binary,\
                    last_test_temp_dir, vpp_pid = keep_alive_parent_end.recv()
            last_heard = time.time()
        if failed_parent_end.fileno() in readable:
            while failed_parent_end.poll():
                failed_test = failed_parent_end.recv()
                failed.add(failed_test.__name__)
            last_heard = time.time()
        fail = False
        if last_heard + test_timeout < time.time() and \
                not os.path.isfile("%s/_core_handled" % last_test_temp_dir):
            fail = True
            global_logger.critical("Timeout while waiting for child test "
                                   "runner process (last test running was "
                                   "`%s' in `%s')!" %
                                   (last_test, last_test_temp_dir))
        elif not child.is_alive():
            fail = True
            global_logger.critical("Child process unexpectedly died (last "
                                   "test running was `%s' in `%s')!" %
                                   (last_test, last_test_temp_dir))
        elif last_test_temp_dir and last_test_vpp_binary:
            core_path = "%s/core" % last_test_temp_dir
            if os.path.isfile(core_path):
                if core_detected_at is None:
                    core_detected_at = time.time()
                elif core_detected_at + core_timeout < time.time():
                    if not os.path.isfile(
                            "%s/_core_handled" % last_test_temp_dir):
                        global_logger.critical(
                            "Child unresponsive and core-file exists in test "
                            "temporary directory!")
                        fail = True

        if fail:
            failed_dir = os.getenv('VPP_TEST_FAILED_DIR')
            lttd = last_test_temp_dir.split("/")[-1]
            link_path = '%s%s-FAILED' % (failed_dir, lttd)
            global_logger.error("Creating a link to the failed " +
                                "test: %s -> %s" % (link_path, lttd))
            try:
                os.symlink(last_test_temp_dir, link_path)
            except:
                pass
            api_post_mortem_path = "/tmp/api_post_mortem.%d" % vpp_pid
            if os.path.isfile(api_post_mortem_path):
                global_logger.error("Copying api_post_mortem.%d to %s" %
                                    (vpp_pid, last_test_temp_dir))
                shutil.copy2(api_post_mortem_path, last_test_temp_dir)
            if last_test_temp_dir and last_test_vpp_binary:
                core_path = "%s/core" % last_test_temp_dir
                if os.path.isfile(core_path):
                    global_logger.error("Core-file exists in test temporary "
                                        "directory: %s!" % core_path)
                    if debug_core:
                        spawn_gdb(last_test_vpp_binary, core_path,
                                  global_logger)
            child.terminate()
            result = -1
            break
    keep_alive_parent_end.close()
    result_parent_end.close()
    failed_parent_end.close()
    return result, failed
Example #26
0
class Hldi:
    cmd_history = []
    cmd_entry_substring = ''
    cmd_history_filename = 'cmd_history.txt'
    # Communication layer.
    com = None
    # Profile is used to manage application settings.
    profile = None
    # All application available profile
    profiles = []

    line_num = 0

    def __init__(self):
        self.bootstrap()

        self.gui_init()

    def bootstrap(self):
        self.com = Uart()

        # Load cmd history.
        try:
            with open(self.cmd_history_filename, 'r') as f:
                self.cmd_history = [line.rstrip('\n') for line in f]
        except:
            pass

        try:
            self.profile = pickle.load(open('profiles.txt', 'r'))
        except:
            self.profile = Profile()

        print self.cmd_history

    def main(self):
        # All PyGTK applications must have a gtk.main(). Control ends here
        # and waits for an event to occur (like a key press or mouse event).
        gtk.main()

    def delete_event(self, widget, event, data=None):
        # If you return FALSE in the "delete_event" signal handler,
        # GTK will emit the "destroy" signal. Returning TRUE means
        # you don't want the window to be destroyed.
        # This is useful for popping up 'are you sure you want to quit?'
        # type dialogs.
        print "delete event occurred"

        # Update history file.
        with open(self.cmd_history_filename, 'w') as f:
            for s in self.cmd_history:
                f.write(s + '\n')

        self.profile.device = self.glade.get_object(
            'serial_device_entry').get_text()
        self.profile.baudrate = self.glade.get_object(
            'serial_baudrate_entry').get_text()

        pickle.dump(self.profile, open('profiles.txt', 'w'))

        # Change FALSE to TRUE and the main window will not be destroyed
        # with a "delete_event".
        return False

    def destroy(self, widget, data=None):
        print "destroy signal occurred"
        gtk.main_quit()

    def com_cmd_on_key_release(self, widget, ev, data=None):
        name = gtk.gdk.keyval_name(ev.keyval)

        if name != 'Up' and name != 'Down' and name != 'Return':
            self.cmd_entry_substring = self.glade.get_object(
                "communication_cmd_entry").get_text()
            print 'cmd substring: %s' % self.cmd_entry_substring

        return True

    # Search entry in cmd history if entry is not empty or list all previously typed commands.
    def com_cmd_on_key_press(self, widget, ev, data=None):
        input = self.glade.get_object("communication_cmd_entry")

        name = gtk.gdk.keyval_name(ev.keyval)

        if name != 'Up' and name != 'Down':
            return

        if not hasattr(self, 'cmd_hist_index'):
            self.cmd_hist_index = -1

        cmd_hist_len = len(self.cmd_history)

        # If cmd entry is not empty search by substring.
        if self.cmd_entry_substring != '':
            origin_index = self.cmd_hist_index

            if name == 'Up':
                self.cmd_hist_index = self.cmd_hist_index - 1

                # Loop through all elements from.
                while origin_index != self.cmd_hist_index:
                    if cmd_hist_len < abs(self.cmd_hist_index):
                        self.cmd_hist_index = -1

                    if re.search(re.escape(self.cmd_entry_substring),
                                 self.cmd_history[self.cmd_hist_index]):
                        input.set_text(self.cmd_history[self.cmd_hist_index])
                        return True

                    self.cmd_hist_index = self.cmd_hist_index - 1

            elif name == 'Down':
                self.cmd_hist_index = self.cmd_hist_index + 1

                # Loop through all elements from.
                while origin_index != self.cmd_hist_index:
                    if cmd_hist_len - 1 < abs(self.cmd_hist_index):
                        self.cmd_hist_index = 0

                    if re.search(re.escape(self.cmd_entry_substring),
                                 self.cmd_history[self.cmd_hist_index]):
                        input.set_text(self.cmd_history[self.cmd_hist_index])
                        return True

                    self.cmd_hist_index = self.cmd_hist_index + 1

        # Otherwise just use prev / next cmd.
        else:
            if name == 'Up':
                self.cmd_hist_index = self.cmd_hist_index - 1
                if cmd_hist_len < abs(self.cmd_hist_index):
                    self.cmd_hist_index = -1

                input.set_text(self.cmd_history[self.cmd_hist_index])
                self.cmd_entry_substring = ''
            elif name == 'Down':
                self.cmd_hist_index = self.cmd_hist_index + 1

                if cmd_hist_len - 1 < abs(self.cmd_hist_index):
                    self.cmd_hist_index = 0

                input.set_text(self.cmd_history[self.cmd_hist_index])
                self.cmd_entry_substring = ''

        return True

    def comm_send(self, input):
        self.com.send(input)

        # Update status bar message.
        statusbar = self.glade.get_object('statusbar')
        context_id = statusbar.get_context_id('last_event')
        statusbar.push(context_id, 'uart: "%s" have been sent' % input)

    def comm_cmd_send(self, input):
        self.comm_send(input)

        textview = self.glade.get_object("communication_output_textview")
        textbuffer = textview.get_buffer()

        self.line_num += 1

        textbuffer.insert(textbuffer.get_end_iter(),
                          '%d: < %s\r\n' % (self.line_num, input))
        textview.scroll_to_mark(textbuffer.get_insert(), 0)

    def comm_cmd_entry_send(self, widget, entry):
        input = self.glade.get_object("communication_cmd_entry").get_text()

        self.comm_send(input)

        textview = self.glade.get_object("communication_output_textview")
        textbuffer = textview.get_buffer()

        self.line_num += 1

        textbuffer.insert(textbuffer.get_end_iter(),
                          '%d: < %s\r\n' % (self.line_num, input))
        textview.scroll_to_mark(textbuffer.get_insert(), 0)

        print '\nbefore\n'
        print self.cmd_history
        # Make list unique.
        if input in self.cmd_history:
            self.cmd_history.remove(input)

        # Make repeated value most recent in cmd history.
        self.cmd_history.append(input)

        self.cmd_hist_index = -1

        print '\nbefore\n'
        print self.cmd_history

        # Avoid further searching if we already entered new string.
        self.cmd_entry_substring = ''
        print 'cmd substring: %s' % self.cmd_entry_substring

    def communication_cmd_enter_callback(self, widget, entry):
        self.comm_cmd_entry_send(widget, entry)

    def communication_send_click_callback(self, widget, data=None):
        self.comm_cmd_entry_send(widget, data)

    def set_speed_btn_on_click(self, widget, data=None):
        if (not self.com.isOpen()):
            self.log('Uart connection is not available', 'error')
            return

        pwm = self.glade.get_object("speed_scale").get_value()

        self.comm_cmd_send(cmd.MOTOR_SET_PWM % pwm)

        # @todo implement true speed once servo & quadrature encoder are done.
        self.glade.get_object('speed_label').set_text('Speed: %d pwm' % pwm)

    def motor_dir_btn_on_click(self, widget, data=None):
        if (not self.com.isOpen()):
            self.log('Uart connection is not available', 'error')
            return

        btn = self.glade.get_object('motor_dir_btn')

        if btn.get_label() == 'CW':
            btn.set_label('CCW')
            self.comm_cmd_send(cmd.MOTOR_CCW)
        else:
            btn.set_label('CW')
            self.comm_cmd_send(cmd.MOTOR_CW)

    def log(self, msg, type='status'):
        # Update status bar message.
        statusbar = self.glade.get_object('statusbar')
        context_id = statusbar.get_context_id('last_event')
        statusbar.push(context_id, '%s: %s' % (type, msg))

    def motor_on_btn_on_click(self, widget, data=None):
        if (not self.com.isOpen()):
            self.log('Uart connection is not available', 'error')
            return

        btn = self.glade.get_object('motor_on_btn')
        spinner = self.glade.get_object('cmd_spinner')

        if btn.get_label() == 'Motor ON':
            btn.set_label('Motor OFF')
            self.comm_cmd_send(cmd.MOTOR_OFF)
            spinner.stop()
        else:
            btn.set_label('Motor ON')
            self.comm_cmd_send(cmd.MOTOR_ON)
            spinner.start()

    def frame_expander_eventbox_click_callback(self,
                                               widget,
                                               data=None,
                                               prefix=''):
        frame_state = '%s_frame_state' % prefix
        origin_viewport_height = '%s_origin_viewport_height' % prefix

        if not hasattr(self, frame_state):
            setattr(self, frame_state, True)

        alignment = self.glade.get_object('%s_alignment' % prefix)
        frame = self.glade.get_object('%s_frame' % prefix)
        viewport = self.glade.get_object('%s_viewport' % prefix)

        if not hasattr(self, origin_viewport_height):
            setattr(self, origin_viewport_height,
                    viewport.get_allocation().height)

        icon = self.glade.get_object('%s_icon' % prefix)

        if getattr(self, frame_state):
            alignment.hide()
            viewport.set_size_request(-1, 40)
            frame.set_shadow_type(gtk.SHADOW_NONE)
            icon.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
        else:
            viewport.set_size_request(-1, getattr(self,
                                                  origin_viewport_height))
            alignment.show()
            frame.set_shadow_type(gtk.SHADOW_ETCHED_OUT)
            icon.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_BUTTON)

        setattr(self, frame_state, getattr(self, frame_state) ^ 1)

    def gui_init(self):
        # Set the Glade file
        self.gladefile = "hldi.glade"
        self.glade = gtk.Builder()

        self.glade.add_from_file(self.gladefile)
        self.glade.connect_signals(self)

        window = self.glade.get_object("MainWindow")

        # When the window is given the "delete_event" signal (this is given
        # by the window manager, usually by the "close" option, or on the
        # titlebar), we ask it to call the delete_event () function
        # as defined above. The data passed to the callback
        # function is NULL and is ignored in the callback function.
        window.connect("delete_event", self.delete_event)

        # Here we connect the "destroy" event to a signal handler.
        # This event occurs when we call gtk_widget_destroy() on the window,
        # or if we return FALSE in the "delete_event" callback.
        window.connect("destroy", self.destroy)

        # Sets the border width of the window.
        # window.set_border_width(10)
        window.set_title('CoreXY HLDI (c) Pavel Ruban')

        # When the button receives the "clicked" signal, it will call the
        # function hello() passing it None as its argument.  The hello()
        # function is defined above.
        self.glade.get_object('communication_send_button').connect(
            'clicked', self.communication_send_click_callback, None)
        self.glade.get_object('connection_eventbox').connect(
            'button-press-event', self.frame_expander_eventbox_click_callback,
            'connection')
        self.glade.get_object('movectrl_eventbox').connect(
            'button-press-event', self.frame_expander_eventbox_click_callback,
            'movectrl')
        self.glade.get_object('communication_cmd_entry').connect(
            'activate', self.communication_cmd_enter_callback, None)
        self.glade.get_object('communication_cmd_entry').connect(
            'key-release-event', self.com_cmd_on_key_release)
        self.glade.get_object('communication_cmd_entry').connect(
            'key-press-event', self.com_cmd_on_key_press)
        self.glade.get_object('serial_connect_button').connect(
            'clicked', self.communication_connect_on_click, None)
        self.glade.get_object('motor_on_btn').connect(
            'clicked', self.motor_on_btn_on_click, None)
        self.glade.get_object('motor_dir_btn').connect(
            'clicked', self.motor_dir_btn_on_click, None)
        self.glade.get_object('set_speed_btn').connect(
            'clicked', self.set_speed_btn_on_click, None)

        # configure the serial connections (the parameters differs on the device you are connecting to)

        try:
            self.glade.get_object('serial_device_entry').set_text(
                self.profile.device)
            self.glade.get_object('serial_baudrate_entry').set_text(
                self.profile.baudrate)
            self.glade.get_object('profile_entry').set_text(self.profile.name)
        except:
            self.glade.get_object('serial_device_entry').set_text(
                '/dev/ttyUSB0')
            self.glade.get_object('serial_baudrate_entry').set_text('115200')
            self.glade.get_object('profile_entry').set_text('photoresist')

        self.glade.get_object("speed_scale").set_range(0, 255)

        # and the window
        window.show_all()

    def communication_connect(self):
        self.com.connect(self.glade)

        time.sleep(1)

        # Create pipe Parent < Child.
        self.parent_conn, self.child_conn = Pipe(duplex=False)

        self.communication_proc = Process(name='self.com',
                                          target=communication_thread,
                                          args=[self.child_conn, queue])
        self.communication_proc.daemon = True
        self.communication_proc.start()

        self.child_conn.close()

    def communication_connect_on_click(self, widget, entry):

        if self.com.isOpen():
            self.com.close()

            self.glade.get_object('serial_connect_button').set_label('connect')

            if hasattr(self, 'communication_proc') and hasattr(
                    self.communication_proc, 'terminate'):
                self.communication_proc.terminate()
        else:
            self.communication_connect()

            if self.com.isOpen():
                self.glade.get_object('serial_connect_button').set_label(
                    'disconnect')

            # Process STDIN of the parnet process with read_data method.
            gobject.io_add_watch(self.parent_conn.fileno(), gobject.IO_IN,
                                 self.communication_read_data)

            self.glade.get_object('serial_connect_button').set_label(
                'disconnect')

    # read values from the child process
    def communication_read_data(self, source, condition):
        self.line_num += 1

        assert self.parent_conn.poll()

        try:
            i = self.parent_conn.recv()
        except EOFError:
            return False  # stop reading

        # @todo delete encoder debug later.
        m = re.match(r'^>> setpos: (-?\d+(?:\.\d+)?)', i)
        if m:
            self.glade.get_object('setpos_label').set_label('sp %.2f' %
                                                            float(m.group(1)))
            vars.set_position.append(float(m.group(1)))
            return True  # continue reading

        m = re.match(r'^>> pos: (-?\d+(?:\.\d+)?)', i)
        if m:
            self.glade.get_object('state_label').set_label(m.group(1))
            self.glade.get_object('pos_label').set_label('pos %.3f' %
                                                         float(m.group(1)))

            vars.position.append(float(m.group(1)))
            last_set_pos = max(enumerate(vars.set_position))[1]
            vars.set_position.append(last_set_pos)

            return True  # continue reading

        m = re.match(r'^>> PID CV: (-?\d+(?:\.\d+)?)', i)
        if m:
            self.glade.get_object('cv_label').set_label('cv %.3f' %
                                                        float(m.group(1)))
            return True  # continue reading

        m = re.match(r'^>> pid i: (-?\d+(?:\.\d+)?)', i)
        if m:
            self.glade.get_object('integral_label').set_label(
                'i %.3f'.encode('utf-8') % float(m.group(1)))
            return True  # continue reading

        m = re.match(r'^>> PID K([pdi]) was set to (-?\d+(?:\.\d+)?)', i)
        if m:
            set_pid_label = {
                'p':
                lambda: self.glade.get_object('kp_label').set_label(
                    'kp %.4f' % float(m.group(2))),
                'd':
                lambda: self.glade.get_object('kd_label').set_label(
                    'kd %.4f' % float(m.group(2))),
                'i':
                lambda: self.glade.get_object('ki_label').set_label(
                    'ki %.4f' % float(m.group(2)))
            }[m.group(1)]

            set_pid_label()

            return True  # continue reading

        # Update text
        textview = self.glade.get_object("communication_output_textview")

        textbuffer = textview.get_buffer()
        textbuffer.insert(textbuffer.get_end_iter(),
                          '%d: %s' % (self.line_num, i))

        textview.scroll_to_mark(textbuffer.get_insert(), 0)

        return True  # continue reading

    def on_MainWindow_delete_event(self, widget, event):
        gtk.main_quit()
Example #27
0
class MultiprocessSingleton:
    """A multi-process singleton (duh)."""

    _instance = None

    def __init__(self):
        """Docstring placeholder."""
        if self.__class__._instance is not None:
            raise SingletonReinitError()
        self._mpsing_lock = Lock()
        self._mpsing_server_conn, self._mpsing_client_conn = Pipe()

    @classmethod
    def instance(cls):
        """Return the local instance of this singleton."""
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    def _ipc_call(self, fn_name, *args, **kwargs):
        """Peform the IPC call, from the client context.

        This method is called in the client context. It sends an RPC request
        to the server, and returns its result.
        """
        if not callable(getattr(self, fn_name)):
            raise TypeError(f"{fn_name} is not callable")
        with self._mpsing_lock:
            msg = (fn_name, args, kwargs)
            self._mpsing_client_conn.send(msg)
            result = self._mpsing_client_conn.recv()
        if isinstance(result, BaseException):
            # TODO: sending the exception through the IPC pipe will strip its
            #       __traceback__ property, as traceback objects cannot be
            #       pickled. It would be nice to send some kind of traceback
            #       info back though.
            raise result
        return result

    def fileno(self):
        """Return a pollable IPC file descriptor.

        The returned FD should be used to determine whether the server needs
        to service any pending requests (i.e. when data is ready to be read
        from the FD).
        """
        return self._mpsing_server_conn.fileno()

    def handle_ipc_call(self):
        """Handle the next IPC call from a client.

        Called only in the server context, this method will perform a blocking
        read from the IPC pipe. If the caller wants to avoid blocking here,
        they should poll/select `self.fileno()` for reading before calling
        this method.
        """
        (fn_name, args, kwargs) = self._mpsing_server_conn.recv()
        try:
            res = getattr(self, fn_name).orig_fn(self, *args, **kwargs)
        # pylint: disable=broad-except
        except BaseException as exc:
            res = exc
        self._mpsing_server_conn.send(res)
Example #28
0
class Worker(Process):
    def __init__(self, endpoint, workport=23456, logport=23457, workerID=None, print_local=True):
        Process.__init__(self)
        self.endpoint = endpoint
        self.workport = workport
        self.logport = logport
        self.workerID = workerID
        self.print_local = print_local

        self._is_stdsocket_setup = False

        if self.workerID is None:
            self.workerID = "worker-" + str(uuid4())

        self.ipcURI = "ipc:///tmp/splark_" + self.workerID + ".ipc"

        # Data id: cloudpickle
        self.data = {}
        self.unsent_stdout = ""

    def setupWorker(self):
        self.inner_recv_pipe, inner_stdout = Pipe(duplex=False)
        # Make the pipe look like the inner worker's stdout. Surprisingly, this works.
        inner_stdout.write = inner_stdout.send
        inner_stdout.flush = lambda: None
        self.inner_worker = InnerWorker(self.ipcURI, daemon=True, stdout=inner_stdout, stderr=inner_stdout)
        self.inner_worker.start()

        self.working = False
        self.workingID = None

    def setupZMQ(self):
        self.ctx = zmq.Context()

        # Setup syncronous comms to master
        self.master_socket = MasterConnection(self.ctx, self.workerID.encode("ascii"))
        self.master_socket.connect(self.endpoint + ":" + str(self.workport))

        # Send the initial worker ID to start a transaction going
        self.master_socket.send_connect()

        # Setup async stdio/stderr
        self.stdsocket = self.ctx.socket(zmq.PUSH)
        self.stdsocket.connect(self.endpoint + ":" + str(self.logport))
        self._is_stdsocket_setup = True

        # Setup IPC to inner worker
        self.inner_socket = self.ctx.socket(zmq.REQ)
        self.inner_socket.bind(self.ipcURI)

    def setupPoller(self):
        self.poller = zmq.Poller()
        self.poller.register(self.master_socket, zmq.POLLIN)
        self.poller.register(self.inner_socket, zmq.POLLIN)
        self.poller.register(self.inner_recv_pipe.fileno(), zmq.POLLIN)

    def setup(self):
        self.log("Initializing.")
        self.setupZMQ()
        self.setupWorker()
        self.setupPoller()
        self.log("Initialization complete.")

    def log(self, *args):
        short_name = self.workerID.split("worker-")[1][:8]
        print_args = ("WORKER " + short_name + " >>>",) + args
        if self.print_local:
            print(*print_args)
        # Buffer this message to be sent over stdout.
        self.unsent_stdout += "\n" + " ".join(print_args) + "\n"
        self.flush_stdout_buffer()

    # All _handle_* functions map 1:1 with API calls
    # They all return a pyobject, which is the serialized
    # response to the call
    def _handle_SETDATA(self, id, blob):
        self.data[id] = blob
        return Commands.OK

    def _handle_DELDATA(self, id):
        try:
            del self.data[id]
            return Commands.TRUE
        except KeyError:
            return Commands.FALSE

    def _handle_GETDATA(self, id):
        try:
            return self.data[id]
        except KeyError as e:
            return toCP(e)

    def _handle_LISTDATA(self):
        return toCP(list(self.data.keys()))

    def _handle_ISWORKING(self):
        return Commands.TRUE if self.working else Commands.FALSE

    def _handle_RESETWORKER(self):
        self.inner_worker.terminate()
        time.sleep(1)
        self.setupWorker()
        return Commands.OK

    def _handle_CALL(self, *ids):
        # Work not queued, already working
        if self.working:
            return False

        *inputIDs, outID = ids

        # All datae must already be here
        if any(idee not in self.data for idee in inputIDs):
            return False

        self.log("Starting work!")
        self.startWork(inputIDs, outID)
        return Commands.OK

    def _handle_PING(self):
        return Commands.OK

    def _handle_DIE(self):
        self.log("Terminating inner worker process.")
        self.inner_worker.terminate()
        self.working = False
        self.log("Exiting.")
        sys.exit(0)

    def processRequest(self):
        # Get the request and arguments from the exterior
        requestType, args = self.master_socket.recv_cmd()

        # Get the handler for this request type
        fHandler = getattr(self, "_handle_" + requestType, None)
        assert fHandler is not None, "No handler for request:" + requestType

        # Call the handler on the remaining arguments
        self.log("RECV \"{}\"".format(requestType))
        result = fHandler(*args)
        self.master_socket.send_response(result)

    def startWork(self, inIDs, outID):
        assert not self.working

        # Dispatch a map to the inner worker
        self.inner_socket.send_multipart(tuple(self.data[id] for id in inIDs))

        # Store state for when we return
        self.workingID = outID
        self.working = True

    def finishWork(self):
        # Return the work unit to the data pool with the above semaphores
        self.data[self.workingID] = self.inner_socket.recv()

        # Clear the semaphors
        self.workingID = None
        self.working = False

    def recv_stdout(self):
        self.unsent_stdout += self.inner_recv_pipe.recv()
        self.flush_stdout_buffer()

    def flush_stdout_buffer(self):
        if not self._is_stdsocket_setup:
            return

        *messages, self.unsent_stdout = self.unsent_stdout.split("\n")
        for message in messages:
            # Ignore blank lines. Ain't nobody got time for that.
            if message == "":
                continue
            if self.print_local:
                print(message)
            self.stdsocket.send_string(message)

    def run(self):
        self.setup()

        while True:
            socks = dict(self.poller.poll())
            # Look for incoming requests
            if socks.get(self.master_socket) == zmq.POLLIN:
                self.processRequest()

            # Finish work orders
            if socks.get(self.inner_socket) == zmq.POLLIN:
                self.finishWork()

            # Pipe inner worker's stdout and stderr to master
            if socks.get(self.inner_recv_pipe.fileno()) == zmq.POLLIN:
                self.recv_stdout()
Example #29
0
class StatsCounter:
    """Counts characters, words, sentences and read time using a worker process."""

    # Regexp that matches any character, except for newlines and subsequent spaces.
    CHARACTERS = re.compile(r"[^\s]|(?:[^\S\n](?!\s))")

    # Regexp that matches Asian letters, general symbols and hieroglyphs,
    # as well as sequences of word characters optionally containing non-word characters in-between.
    WORDS = re.compile(r"[\u3040-\uffff]|(?:\w+\S?\w*)+", re.UNICODE)

    # Regexp that matches sentence-ending punctuation characters, ie. full stop, question mark,
    # exclamation mark, paragraph, and variants.
    SENTENCES = re.compile(r"[^\n][.。।෴۔።?՞;⸮؟?፧꘏⳺⳻⁇﹖⁈⁉‽!﹗!՜߹႟᥄\n]+")

    # Regexp that matches paragraphs, ie. anything separated by at least 2 newlines.
    PARAGRAPHS = re.compile(r"[^\n]+(\n{2,}|$)")

    # List of regexp whose matches should be replaced by their "text" group. Order is important.
    MARKUP_REGEXP_REPLACE = (BOLD_ITALIC, ITALIC_ASTERISK, ITALIC_UNDERSCORE,
                             BOLD, STRIKETHROUGH, IMAGE, LINK, LINK_ALT, LIST,
                             ORDERED_LIST, BLOCK_QUOTE, HEADER, HEADER_UNDER,
                             CODE_BLOCK, TABLE, MATH, FOOTNOTE_ID, FOOTNOTE)

    # List of regexp whose matches should be removed. Order is important.
    MARKUP_REGEXP_REMOVE = (HORIZONTAL_RULE, )

    def __init__(self, callback):
        super().__init__()

        # Worker process to handle counting.
        self.counting = False
        self.count_pending_text = None
        self.parent_conn, child_conn = Pipe()
        Process(target=self.do_count, args=(child_conn, ), daemon=True).start()
        GLib.io_add_watch(self.parent_conn.fileno(), GLib.PRIORITY_LOW,
                          GLib.IO_IN, self.on_counted, callback)

    def count(self, text):
        """Count stats for text.

        In case counting is already running, it will re-count once it finishes. This ensure that
        the pipe doesn't fill (and block) if multiple requests are made in quick succession."""

        if not self.counting:
            self.counting = True
            self.count_pending_text = None
            self.parent_conn.send(text)
        else:
            self.count_pending_text = text

    def do_count(self, child_conn):
        """Counts stats in a worker process.

        The result is in the format: (characters, words, sentences, (hours, minutes, seconds))"""

        while True:
            while True:
                try:
                    text = child_conn.recv()
                    if not child_conn.poll():
                        break
                except EOFError:
                    child_conn.close()
                    return

            for regexp in self.MARKUP_REGEXP_REPLACE:
                text = re.sub(regexp, r"\g<text>", text)
            for regexp in self.MARKUP_REGEXP_REMOVE:
                text = re.sub(regexp, "", text)

            character_count = len(re.findall(self.CHARACTERS, text))
            word_count = len(re.findall(self.WORDS, text))
            sentence_count = len(re.findall(self.SENTENCES, text))
            paragraph_count = len(re.findall(self.PARAGRAPHS, text))

            read_m, read_s = divmod(word_count / 200 * 60, 60)
            read_h, read_m = divmod(read_m, 60)
            read_time = (int(read_h), int(read_m), int(read_s))

            child_conn.send((character_count, word_count, sentence_count,
                             paragraph_count, read_time))

    def on_counted(self, _source, _condition, callback):
        """Reads the counting result from the pipe and triggers any pending count."""

        self.counting = False
        if self.count_pending_text is not None:
            self.count(
                self.count_pending_text)  # self.count clears the pending text.

        try:
            if self.parent_conn.poll():
                callback(self.parent_conn.recv())
            return True
        except EOFError:
            return False

    def stop(self):
        """Stops the worker process. StatsCounter shouldn't be used after this."""
        print("stop counter")
        self.parent_conn.close()
Example #30
0
class MarkupHandler:
    TAG_NAME_ITALIC = 'italic'
    TAG_NAME_BOLD = 'bold'
    TAG_NAME_BOLD_ITALIC = 'bold_italic'
    TAG_NAME_STRIKETHROUGH = 'strikethrough'
    TAG_NAME_CENTER = 'center'
    TAG_NAME_WRAP_NONE = 'wrap_none'
    TAG_NAME_PLAIN_TEXT = 'plain_text'
    TAG_NAME_GRAY_TEXT = 'gray_text'
    TAG_NAME_CODE_TEXT = 'code_text'
    TAG_NAME_CODE_BLOCK = 'code_block'
    TAG_NAME_UNFOCUSED_TEXT = 'unfocused_text'
    TAG_NAME_MARGIN_INDENT = 'margin_indent'

    def __init__(self, text_view):
        self.text_view = text_view
        self.text_buffer = text_view.get_buffer()
        self.marked_up_text = None

        # Tags.
        buffer = self.text_buffer

        self.tag_italic = buffer.create_tag(self.TAG_NAME_ITALIC,
                                            weight=Pango.Weight.NORMAL,
                                            style=Pango.Style.ITALIC)

        self.tag_bold = buffer.create_tag(self.TAG_NAME_BOLD,
                                          weight=Pango.Weight.BOLD,
                                          style=Pango.Style.NORMAL)

        self.tag_bold_italic = buffer.create_tag(self.TAG_NAME_BOLD_ITALIC,
                                                 weight=Pango.Weight.BOLD,
                                                 style=Pango.Style.ITALIC)

        self.tag_strikethrough = buffer.create_tag(self.TAG_NAME_STRIKETHROUGH,
                                                   strikethrough=True)

        self.tag_center = buffer.create_tag(
            self.TAG_NAME_CENTER, justification=Gtk.Justification.CENTER)

        self.tag_wrap_none = buffer.create_tag(self.TAG_NAME_WRAP_NONE,
                                               wrap_mode=Gtk.WrapMode.NONE,
                                               pixels_above_lines=0,
                                               pixels_below_lines=0)

        self.tag_plain_text = buffer.create_tag(
            self.TAG_NAME_PLAIN_TEXT,
            weight=Pango.Weight.NORMAL,
            style=Pango.Style.NORMAL,
            strikethrough=False,
            justification=Gtk.Justification.LEFT)

        self.tag_gray_text = buffer.create_tag(self.TAG_NAME_GRAY_TEXT,
                                               foreground='gray',
                                               weight=Pango.Weight.NORMAL,
                                               style=Pango.Style.NORMAL)

        self.tag_code_text = buffer.create_tag(self.TAG_NAME_CODE_TEXT,
                                               weight=Pango.Weight.NORMAL,
                                               style=Pango.Style.NORMAL,
                                               strikethrough=False)

        self.tag_code_block = buffer.create_tag(self.TAG_NAME_CODE_BLOCK,
                                                weight=Pango.Weight.NORMAL,
                                                style=Pango.Style.NORMAL,
                                                strikethrough=False,
                                                indent=self.get_margin_indent(
                                                    0, 1)[1])

        self.tags_markup = {
            self.TAG_NAME_ITALIC:
            lambda args: self.tag_italic,
            self.TAG_NAME_BOLD:
            lambda args: self.tag_bold,
            self.TAG_NAME_BOLD_ITALIC:
            lambda args: self.tag_bold_italic,
            self.TAG_NAME_STRIKETHROUGH:
            lambda args: self.tag_strikethrough,
            self.TAG_NAME_CENTER:
            lambda args: self.tag_center,
            self.TAG_NAME_WRAP_NONE:
            lambda args: self.tag_wrap_none,
            self.TAG_NAME_PLAIN_TEXT:
            lambda args: self.tag_plain_text,
            self.TAG_NAME_GRAY_TEXT:
            lambda args: self.tag_gray_text,
            self.TAG_NAME_CODE_TEXT:
            lambda args: self.tag_code_text,
            self.TAG_NAME_CODE_BLOCK:
            lambda args: self.tag_code_block,
            self.TAG_NAME_MARGIN_INDENT:
            lambda args: self.get_margin_indent_tag(*args)
        }

        # Focus mode.
        self.tag_unfocused_text = buffer.create_tag(
            self.TAG_NAME_UNFOCUSED_TEXT,
            foreground='gray',
            weight=Pango.Weight.NORMAL,
            style=Pango.Style.NORMAL)

        # Margin and indents.
        # A baseline margin is set to allow negative offsets for formatting
        # headers, lists, etc.
        self.tags_margins_indents = {}
        self.baseline_margin = 0
        self.char_width = 0
        self.update_margins_indents()

        # Style.
        self.on_style_updated()

        # Worker process to handle parsing.
        self.parsing = False
        self.apply_pending = False
        self.parent_conn, child_conn = Pipe()
        Process(target=self.parse, args=(child_conn, ), daemon=True).start()
        GLib.io_add_watch(self.parent_conn.fileno(), GLib.PRIORITY_DEFAULT,
                          GLib.IO_IN, self.on_parsed)

    def on_style_updated(self, *_):
        style_context = self.text_view.get_style_context()
        (found, color) = style_context.lookup_color('code_bg_color')
        if not found:
            (_, color) = style_context.lookup_color('background_color')
        self.tag_code_text.set_property("background", color.to_string())
        self.tag_code_block.set_property("paragraph-background",
                                         color.to_string())

    def apply(self):
        """Applies markup, parsing it in a worker process
        if the text has changed.

        In case parsing is already running, it will re-apply once it finishes.
        This ensure that the pipe doesn't fill (and block) if multiple requests
        are made in quick succession."""

        if not self.parsing:
            self.parsing = True
            self.apply_pending = False

            text = self.text_buffer.get_slice(
                self.text_buffer.get_start_iter(),
                self.text_buffer.get_end_iter(), False)
            if text != self.marked_up_text:
                self.parent_conn.send(text)
            else:
                self.do_apply(text)
        else:
            self.apply_pending = True

    def parse(self, child_conn):
        """Parses markup in a worker process."""

        while True:
            while True:
                try:
                    text = child_conn.recv()
                    if not child_conn.poll():
                        break
                except EOFError:
                    child_conn.close()
                    return

            # List of tuples in the form (tag_name, tag_args, tag_start,
            # tag_end).
            result = []

            # Find:
            # - "_italic_" (italic)
            # - "**bold**" (bold)
            # - "***bolditalic***" (bold/italic)
            # - "~~strikethrough~~" (strikethrough)
            # - "`code`" (colorize)
            # - "$math$" (colorize)
            # - "---" table (wrap/pixels)
            regexps = ((ITALIC_ASTERISK, self.TAG_NAME_ITALIC),
                       (ITALIC_UNDERSCORE, self.TAG_NAME_ITALIC),
                       (BOLD, self.TAG_NAME_BOLD), (BOLD_ITALIC,
                                                    self.TAG_NAME_BOLD_ITALIC),
                       (STRIKETHROUGH, self.TAG_NAME_STRIKETHROUGH),
                       (CODE, self.TAG_NAME_CODE_TEXT),
                       (MATH,
                        self.TAG_NAME_CODE_TEXT), (TABLE,
                                                   self.TAG_NAME_WRAP_NONE))
            for regexp, tag_name in regexps:
                matches = re.finditer(regexp, text)
                for match in matches:
                    result.append((tag_name, (), match.start(), match.end()))

            # Find:
            # - "[description](url)" (gray out)
            # - "![description](image_url)" (gray out)
            regexps = ((LINK, self.TAG_NAME_GRAY_TEXT),
                       (IMAGE, self.TAG_NAME_GRAY_TEXT))
            for regexp, tag_name in regexps:
                matches = re.finditer(regexp, text)
                for match in matches:
                    result.append(
                        (tag_name, (), match.start(), match.start("text")))
                    result.append(
                        (tag_name, (), match.end("text"), match.end()))

            # Find "<url>" links (gray out).
            matches = re.finditer(LINK_ALT, text)
            for match in matches:
                result.append(
                    (self.TAG_NAME_GRAY_TEXT, (), match.start("text"),
                     match.end("text")))

            # Find "---" horizontal rule (center).
            matches = re.finditer(HORIZONTAL_RULE, text)
            for match in matches:
                result.append(
                    (self.TAG_NAME_CENTER, (), match.start("symbols"),
                     match.end("symbols")))

            # Find "* list" (offset).
            matches = re.finditer(LIST, text)
            for match in matches:
                # Lists use character+space (eg. "* ").
                length = 2
                nest = len(match.group("indent").replace("    ", "\t"))
                margin = -length - 2 * nest
                indent = -length - 2 * length * nest
                result.append((self.TAG_NAME_MARGIN_INDENT, (margin, indent),
                               match.start("content"), match.end("content")))

            # Find "1. ordered list" (offset).
            matches = re.finditer(ORDERED_LIST, text)
            for match in matches:
                # Ordered lists use numbers/letters+dot/parens+space
                # (eg. "123. ").
                length = len(match.group("prefix")) + 1
                nest = len(match.group("indent").replace("    ", "\t"))
                margin = -length - 2 * nest
                indent = -length - 2 * length * nest
                result.append((self.TAG_NAME_MARGIN_INDENT, (margin, indent),
                               match.start("content"), match.end("content")))

            # Find "> blockquote" (offset).
            matches = re.finditer(BLOCK_QUOTE, text)
            for match in matches:
                result.append((self.TAG_NAME_MARGIN_INDENT, (2, -2),
                               match.start(), match.end()))

            # Find "# Header" (offset+bold).
            matches = re.finditer(HEADER, text)
            for match in matches:
                margin = -len(match.group("level")) - 1
                result.append((self.TAG_NAME_MARGIN_INDENT, (margin, 0),
                               match.start(), match.end()))
                result.append(
                    (self.TAG_NAME_BOLD, (), match.start(), match.end()))

            # Find "=======" header underline (bold).
            matches = re.finditer(HEADER_UNDER, text)
            for match in matches:
                result.append(
                    (self.TAG_NAME_BOLD, (), match.start(), match.end()))

            # Find "```" code block tag (offset + colorize paragraph).
            matches = re.finditer(markup_regex.CODE_BLOCK, text)
            for match in matches:
                result.append((self.TAG_NAME_CODE_BLOCK, (),
                               match.start("block"), match.end("block")))

            # Send parsed data back.
            child_conn.send((text, result))

    def on_parsed(self, _source, _condition):
        """Reads the parsing result from the pipe
        and triggers any pending apply."""

        self.parsing = False
        if self.apply_pending:
            self.apply()  # self.apply clears the apply pending flag.

        try:
            if self.parent_conn.poll():
                self.do_apply(*self.parent_conn.recv())
            return True
        except EOFError:
            return False

    def do_apply(self, original_text, result=[]):
        """Applies the result of parsing if the current text
        matches the original text."""

        buffer = self.text_buffer
        start = buffer.get_start_iter()
        end = buffer.get_end_iter()
        text = self.text_buffer.get_slice(start, end, False)

        # Apply markup tags.
        if text == original_text and text != self.marked_up_text:
            buffer.remove_tag(self.tag_italic, start, end)
            buffer.remove_tag(self.tag_bold, start, end)
            buffer.remove_tag(self.tag_bold_italic, start, end)
            buffer.remove_tag(self.tag_strikethrough, start, end)
            buffer.remove_tag(self.tag_center, start, end)
            buffer.remove_tag(self.tag_plain_text, start, end)
            buffer.remove_tag(self.tag_gray_text, start, end)
            buffer.remove_tag(self.tag_code_text, start, end)
            buffer.remove_tag(self.tag_code_block, start, end)
            buffer.remove_tag(self.tag_wrap_none, start, end)
            for tag in self.tags_margins_indents.values():
                buffer.remove_tag(tag, start, end)

            for tag_name, tag_args, tag_start, tag_end in result:
                buffer.apply_tag(self.tags_markup[tag_name](tag_args),
                                 buffer.get_iter_at_offset(tag_start),
                                 buffer.get_iter_at_offset(tag_end))

        # Apply focus mode tag (grey out before/after current sentence).
        buffer.remove_tag(self.tag_unfocused_text, start, end)
        if self.text_view.focus_mode:
            cursor_iter = buffer.get_iter_at_mark(buffer.get_insert())
            start_sentence = cursor_iter.copy()
            if not start_sentence.starts_sentence():
                start_sentence.backward_sentence_start()
            end_sentence = cursor_iter.copy()
            if not end_sentence.ends_sentence():
                end_sentence.forward_sentence_end()
            buffer.apply_tag(self.tag_unfocused_text, start, start_sentence)
            buffer.apply_tag(self.tag_unfocused_text, end_sentence, end)

    # Margin and indent are cumulative. They differ in two ways:
    # * Margin is always in the beginning,
    # which means it effectively only affects the first line
    # of multi-line text. Indent is applied to every line.
    # * Margin level can be negative, as a baseline margin exists
    # from which it can be subtracted.
    # Indent is always positive, or 0.
    def get_margin_indent_tag(self, margin_level, indent_level):
        level = (margin_level, indent_level)
        if level not in self.tags_margins_indents:
            margin, indent = self.get_margin_indent(margin_level, indent_level)
            tag = self.text_buffer.create_tag("margin_indent_{}_{}".format(
                margin_level, indent_level),
                                              left_margin=margin,
                                              indent=indent)
            self.tags_margins_indents[level] = tag
            return tag
        else:
            return self.tags_margins_indents[level]

    def get_margin_indent(self,
                          margin_level,
                          indent_level,
                          baseline_margin=None,
                          char_width=None):
        if baseline_margin is None:
            baseline_margin = self.text_view.props.left_margin
        if char_width is None:
            char_width = helpers.get_char_width(self.text_view)
        margin = max(baseline_margin + char_width * margin_level, 0)
        indent = char_width * indent_level
        return margin, indent

    def update_margins_indents(self):
        baseline_margin = self.text_view.props.left_margin
        char_width = helpers.get_char_width(self.text_view)

        # Bail out if neither the baseline margin nor character width change
        if baseline_margin == self.baseline_margin and char_width == self.char_width:
            return
        self.baseline_margin = baseline_margin
        self.char_width = char_width

        # Adjust tab size
        tab_array = Pango.TabArray.new(1, True)
        tab_array.set_tab(0, Pango.TabAlign.LEFT, 4 * char_width)
        self.text_view.set_tabs(tab_array)

        # Adjust margins and indents
        for level, tag in self.tags_margins_indents.items():
            margin, indent = self.get_margin_indent(*level, baseline_margin,
                                                    char_width)
            tag.set_properties(left_margin=margin, indent=indent)

    def stop(self, *_):
        self.parent_conn.close()
Example #31
0
    def __init__(self, device):
        super(Plot, self).__init__()
        self.device = device
        self.set_hexpand(True)
        self.set_vexpand(True)

        fig = Figure()
        fig.subplots_adjust(top=1,
                            bottom=0.09,
                            right=1,
                            left=0.065,
                            hspace=0.2,
                            wspace=0.2)

        self.ax = fig.add_subplot(111, fc='black')
        self._def_axis(self.ax)

        canvas = FigureCanvas(fig)

        canvas.set_size_request(600, 600)
        self.add(canvas)

        parent_conn, self.child_conn = Pipe(
            duplex=False)  # Pipe to pump the label data through

        def update_self(source, condition):
            """
            watches pipe and when data changes, changes the label
            """
            print('source = ', source, 'condition = ', condition)
            assert parent_conn.poll()
            data = parent_conn.recv()

            samples = data['values']

            ys = []
            tmp = 0

            sample_time = 1 / device.get_sampling_speed()

            val = 0
            vals = ['S', 'mS', 'uS', 'nS', 'pS']
            for val in range(0, len(vals)):
                if sample_time > 10:
                    break
                sample_time = sample_time * 1000

            print('scaled and vals set to ', vals[val])

            tmp = 0
            for y in range(len(samples)):
                ys.append(tmp)
                tmp = tmp + 1 / sample_time

            self._def_axis(self.ax)
            self.ax.set_xlabel('Time [%s]' % vals[val])
            self.ax.plot(ys, samples, **self.graph_properties)

            if data['trig_low'] is not None:
                self.ax.axhline(y=data['trig_low'], color='b', linestyle=':')
            if data['trig_up'] is not None:
                self.ax.axhline(y=data['trig_up'], color='b', linestyle=':')
            if data['trig_place'] is not None:
                self.ax.axvline(x=data['trig_place'] * sample_time,
                                color='r',
                                linestyle=':')

            self.queue_draw()
            return True

        GObject.io_add_watch(parent_conn.fileno(), GObject.IO_IN, update_self)