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
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
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
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))
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()
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))
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)
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()
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
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)
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
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
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
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)
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()
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
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)
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
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
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()
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)
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()
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()
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()
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)