def test_timeout(self): A, B = socket.socketpair() # specific user timeout A.settimeout(0.1) # some games so that the test won't hang if recv() never times out def op(sock): try: sock.recv(10) assert False, "Missed expected Timeout" except socket.error: return sock opA = cothread.Spawn(op, A, raise_on_wait=True) try: V = opA.Wait(1.0) except: opA.AbortWait() raise self.assertTrue(V is A) opB = cothread.Spawn(op, B, raise_on_wait=True) try: V = opB.Wait(2.0) except: opB.AbortWait() raise self.assertTrue(V is B) A.close() B.close()
def add_listener(self, listener): """Add callback function that will be called on value, connection and error update :param Subscription listener: Subscription object """ assert listener not in self._listeners, \ "Channel {} already has a listener {}".format(self.name, listener) self._listeners.append(listener) if len(self._listeners) == 1: # This will do the connected callback self.connect() else: # Do a connected and value callback ourself cothread.Spawn(self.do_cb_connection) cothread.Spawn(self.do_cb_value)
def test_server_txrx(self): A = socket.socket() A.bind(('localhost', 0)) A.listen(1) B = socket.socket() B.bind(('localhost', 0)) Sname = A.getsockname() Cname = B.getsockname() def server(): C, peer = A.accept() self.assertEqual(peer, Cname) C.send(b'hello') C.close() server = cothread.Spawn(server, raise_on_wait=True) try: B.connect(Sname) msg = B.recv(100) B.close() except socket.error: # ensure we capture server exceptions... server.Wait(1.0) raise # only get here if no server exception else: server.Wait(1.0) A.close() self.assertEqual(msg, b'hello')
def test_pair_makefile(self): """Test makefile() with socketpair() which behave differently than a plain socket() in python 2.X These must behave like a socket._fileobject wrapping a raw _socket.socket. Closing a _socket.socket is immediate, and necessary to terminate readlines() """ sA, sB = socket.socketpair() A, B = sA.makefile('w'), sB.makefile('r') self.assertNotEqual(A._sock.fileno(), -1) self.assertNotEqual(B._sock.fileno(), -1) def tx2(): for i in range(10): print(i, file=A) A.close() # flush... sA.close() # Actually close the socket, completes readlines() tx2 = cothread.Spawn(tx2, raise_on_wait=True) Ls = B.readlines() B.close() tx2.Wait(1.0) sB.close() self.assertEqual(Ls, [ '0\n', '1\n', '2\n', '3\n', '4\n', '5\n', '6\n', '7\n', '8\n', '9\n' ])
def __init__(self, queue, bpm, server): self.queue = queue self.server = server self.running = True self.process = cothread.Spawn(self.__subscriber, bpm) self.bpm = bpm
def get(self, name, request=None, timeout=5.0, throw=True): """Fetch current value of some number of PVs. :param name: A single name string or list of name strings :param request: A :py:class:`p4p.Value` or string to qualify this request, or None to use a default. :param float timeout: Operation timeout in seconds :param bool throw: When true, operation error throws an exception. If False then the Exception is returned instead of the Value :returns: A p4p.Value or Exception, or list of same. Subject to :py:ref:`unwrap`. When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values >>> ctxt = Context('pva') >>> V = ctxt.get('pv:name') >>> A, B = ctxt.get(['pv:1', 'pv:2']) >>> """ singlepv = isinstance(name, (bytes, unicode)) if singlepv: return self._get_one(name, request=request, timeout=timeout, throw=throw) elif request is None: request = [None] * len(name) assert len(name) == len(request), (name, request) return cothread.WaitForAll( [cothread.Spawn(self._get_one, N, request=R, timeout=timeout, throw=throw, raise_on_wait=True) for N, R in zip(name, request)] )
def test_run_returns_in_ABORTED_state_when_aborted(self): # Add our forever running part forever_part = RunForeverPart(mri="childBlock", name="forever_part", initial_visibility=True) self.c.add_part(forever_part) # Configure our block duration = 0.1 line1 = LineGenerator("y", "mm", 0, 2, 3) line2 = LineGenerator("x", "mm", 0, 2, 2, alternate=True) compound = CompoundGenerator([line1, line2], [], [], duration) self.b.configure(generator=compound, axesToMove=["x"]) # Spawn the abort thread abort_thread = cothread.Spawn(self.abort_after_1s, raise_on_wait=True) # Do the run, which will be aborted with self.assertRaises(AbortedError): self.b.run() self.checkState(self.ss.ABORTED) # Check the abort thread didn't raise abort_thread.Wait(1.0)
def test_spawn_unlocked(self): def set_v1(): self.v = 1 # check our setter works in isolation cothread.Spawn(set_v1).Wait() assert self.v == 1 # now do a long running task works with self.o: self.v = 2 assert self.v == 2 cothread.Spawn(set_v1).Wait() assert self.v == 1 assert self.v == 1
def fill_buffer_array(pvs, length, **kargs): return cothread.WaitForAll([ cothread.Spawn(fill_buffer_one, pv, length, raise_on_wait=True, **kargs) for pv in pvs ])
def __init__(self, func, args, kwargs): # type: (Callable[..., Any], Tuple, Dict) -> None self._result_queue = Queue() self._result = self.NO_RESULT # type: Union[T, Exception] self._function = func self._args = args self._kwargs = kwargs cothread.Spawn(self.catching_function, stack_size=get_stack_size())
def __init__(self, func: Callable[..., Any], args: Tuple, kwargs: Dict) -> None: self._result_queue = Queue() self._result: Union[Any, Exception] = self.NO_RESULT self._function = func self._args = args self._kwargs = kwargs cothread.Spawn(self.catching_function, stack_size=get_stack_size())
def test_run_shutdown(self): task = cothread.Spawn(self.serv.serve_forever, raise_on_wait=True) # Ensure we don't fall through immediately self.assertRaises(cothread.Timedout, task.Wait, 0.1) self.serv.shutdown() task.Wait(1.0)
def server(): server = socket.socket() server.bind(('localhost', PORT)) server.listen(5) print('Running echo server') while True: sock, addr = server.accept() cothread.Spawn(run_service, sock, addr)
def __init__(self, name, cb, notify_disconnect=False): self.name, self._S, self._cb = name, None, cb self._notify_disconnect = notify_disconnect self._Q = cothread.EventQueue() if notify_disconnect: self._Q.Signal(Disconnected()) # all subscriptions are inittially disconnected self._T = cothread.Spawn(self._handle)
def put(self, name, values, request=None, process=None, wait=None, timeout=5.0, get=True, throw=True): """Write a new value of some number of PVs. :param name: A single name string or list of name strings :param values: A single value, a list of values, a dict, a `Value`. May be modified by the constructor nt= argument. :param request: A :py:class:`p4p.Value` or string to qualify this request, or None to use a default. :param float timeout: Operation timeout in seconds :param bool throw: When true, operation error throws an exception. If False then the Exception is returned instead of the Value :param str process: Control remote processing. May be 'true', 'false', 'passive', or None. :param bool wait: Wait for all server processing to complete. :param bool get: Whether to do a Get before the Put. If True then the value passed to the builder callable will be initialized with recent PV values. eg. use this with NTEnum to find the enumeration list. :returns: A None or Exception, or list of same When invoked with a single name then returns is a single value. When invoked with a list of name, then returns a list of values If 'wait' or 'process' is specified, then 'request' must be omitted or None. >>> ctxt = Context('pva') >>> ctxt.put('pv:name', 5.0) >>> ctxt.put(['pv:1', 'pv:2'], [1.0, 2.0]) >>> ctxt.put('pv:name', {'value':5}) >>> The provided value(s) will be automatically coerced to the target type. If this is not possible then an Exception is raised/returned. Unless the provided value is a dict, it is assumed to be a plain value and an attempt is made to store it in '.value' field. """ if request and (process or wait is not None): raise ValueError("request= is mutually exclusive to process= or wait=") elif process or wait is not None: request = 'field()record[block=%s,process=%s]' % ('true' if wait else 'false', process or 'passive') singlepv = isinstance(name, (bytes, unicode)) if singlepv: return self._put_one(name, values, request=request, timeout=timeout, throw=throw, get=get) elif request is None: request = [None] * len(name) assert len(name) == len(request), (name, request) assert len(name) == len(values), (name, values) return cothread.WaitForAll( [cothread.Spawn(self._put_one, N, V, request=R, timeout=timeout, throw=throw, get=get, raise_on_wait=True) for N, V, R in zip(name, values, request)] )
def test_signalled(self): l = [] def waiter(): l.append(self.o.Wait()) s = cothread.Spawn(waiter) # Check that it's blocked self.assertRaises(cothread.Timedout, s.Wait, 0.1) self.o.Signal(46) s.Wait(0.1) assert l == [46]
def __init__(self, bpm, server, volume): self.server = server self.volume = volume self.channels = 'b' cothread.Spawn(self.player) self.queue = cothread.EventQueue() self.sub = None # Hang onto input volume level history for last 5 seconds. self.mvolume = 100 * numpy.ones(50) self.set_bpm(bpm)
def test_spawn_locked(self): def set_v1(): with self.o: self.v = 1 # check our setter works in isolation assert self.v is None cothread.Spawn(set_v1).Wait() assert self.v == 1 # now do a long running task works with self.o: self.v = 2 assert self.v == 2 # start our thing that will be blocked, then sleep to make sure # it can't do its thing s = cothread.Spawn(set_v1) cothread.Sleep(0.2) assert self.v == 2 # now wait for the other to complete, and check it could s.Wait() assert self.v == 1
def _starter(self, raise_on_wait): _LOGGER.debug("VirtualAccelerator: Start (cothread)") if self._started: raise RuntimeError("VirtualAccelerator: Already started") if not os.path.isdir(self.data_dir): raise RuntimeError("VirtualAccelerator: Data directory not found: {}".format(self.data_dir)) if self.work_dir is not None and os.path.exists(self.work_dir): raise RuntimeError("VirtualAccelerator: Working directory already exists: {}".format(self.work_dir)) self._started = True self._continue = True self._executer = cothread.Spawn(self._executer, raise_on_wait=raise_on_wait)
def test_pair_makefile(self): """Test makefile() with socketpair() In python2.x they behave differently than a plain socket(). They must behave like a socket._fileobject wrapping a raw _socket.socket. Closing a _socket.socket is immediate, and necessary to terminate readlines() In python 3.X they behaves the same as a plain socket(). Underlying socket is a reference count. So the socket in actually closed when the last reference is released. """ sA, sB = socket.socketpair() A, B = sA.makefile('w'), sB.makefile('r') if sys.version_info < (3, ): self.assertNotEqual(A._sock.fileno(), -1) self.assertNotEqual(B._sock.fileno(), -1) else: sA.close() sB.close() self.assertNotEqual(A.name, -1) self.assertNotEqual(B.name, -1) def tx2(): for i in range(10): print(i, file=A) if sys.version_info < (3, ): A.close() # flush... sA.close() # Actually close the socket, completes readlines() else: A.close() # flush and close tx2 = cothread.Spawn(tx2, raise_on_wait=True) Ls = B.readlines() B.close() tx2.Wait(1.0) if sys.version_info < (3, ): sB.close() self.assertEqual(Ls, [ '0\n', '1\n', '2\n', '3\n', '4\n', '5\n', '6\n', '7\n', '8\n', '9\n' ])
def setSequence(self): T, C = [], [] for x in range(self.ui.tableWidget.rowCount()): nextC = self.ui.tableWidget.item(x,0) nextT = self.ui.tableWidget.item(x,1) if nextC is None and nextT is None: break # Done elif nextC is None or nextT is None: self.msg("Incomplete sequence.") return nextC, nextT = str(nextC.text()), str(nextT.text()) if not nextC and not nextT: break # Done elif not nextC or not nextT: self.msg("Incomplete sequence.") return try: nextC = int(nextC,0) if nextC <= 0 or nextC > 255: self.msg("Code %d must be in range [0,255]"%nextC) return except ValueError: self.msg("Code '%s' must be an integer"%nextC) return try: nextT = float(nextT) if nextT < 0: self.msg("Time %d must be >=0"%nextT) return except ValueError: self.msg("Time '%s' must be a positive number"%nextT) return T.append(nextT) C.append(nextC) if len(T)==0 or len(C)==0: self.msg("No data to send...") return self.codes, self.times = [], [] self.msg('Sending...', 4000) cothread.Spawn(self._setpvs, T, C)
def _co_start(self, raise_on_wait): _LOGGER.debug("VA: Start (cothread)") if self._started: raise RuntimeError("VA: Already started") if not os.path.isdir(self.data_dir): raise RuntimeError("VA: Data directory not found: {}".format(self.data_dir)) else: _LOGGER.info(f"VA: Loading FLAME data at: {self.data_dir}") if self.work_dir is not None and os.path.exists(self.work_dir): raise RuntimeError("VA: Working directory already exists: {}".format(self.work_dir)) self._started = True self._continue = True self._wait_event.Reset() cothread.Spawn(self._co_execute_with_cleanup, raise_on_wait, raise_on_wait=False)
def test_server_makefile(self): """Test makefile() with socket() which behave differently than socketpair() in python 2.X These must behave like a socket._fileobject wrapping a socket.socket. Closing a socket.socket decrements a ref counter which does not close the socket as a ref is held by the _fileobject. So here (as with many library modules) we depend on the GC to close the socket when the _fileobject is collected. """ A = socket.socket() A.bind(('localhost', 0)) A.listen(1) B = socket.socket() B.bind(('localhost', 0)) Sname = A.getsockname() Cname = B.getsockname() def server(): C, peer = A.accept() self.assertEqual(peer, Cname) F = C.makefile(mode='w') C.close() F.write('hello') F.close() server = cothread.Spawn(server, raise_on_wait=True) try: B.connect(Sname) fB = B.makefile(mode='r') B.close() msg = fB.readline() fB.close() except socket.error: # ensure we capture server exceptions... server.Wait(1.0) raise # only get here if no server exception else: server.Wait(1.0) A.close() self.assertEqual(msg, 'hello')
def start_ioc(stats, prefix): db_macros = "prefix='%s'" % prefix try: epics_base = os.environ["EPICS_BASE"] except KeyError: raise BadValueError("EPICS base not defined in environment") softIoc_bin = epics_base + "/bin/linux-x86_64/softIoc" for key, value in stats.items(): db_macros += ",%s='%s'" % (key, value) root = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0] db_template = os.path.join(root, "db", "system.template") ioc = subprocess.Popen( [softIoc_bin, "-m", db_macros, "-d", db_template], stdout=subprocess.PIPE, stdin=subprocess.PIPE, ) cothread.Spawn(await_ioc_start, stats, prefix) return ioc
def _co_execute_with_cleanup(self, raise_on_wait): """Executer method wraps the call to _execute and ensure that the proper clean up of connections and processes. """ _LOGGER.debug("VA: Execute (cothread)") execute_error = None try: cothread.Spawn(self._co_execute, raise_on_wait=raise_on_wait).Wait() except Exception as e: execute_error = e finally: _LOGGER.info("VA: Cleanup") if self._subscriptions is not None: _LOGGER.debug("VA: Cleanup: close connections") for sub in self._subscriptions: sub.close() self._subscriptions = None if self._ioc_process is not None: _LOGGER.debug("VA: Cleanup: terminate IOC process") self._ioc_process.terminate() self._ioc_process.wait() self._ioc_process = None if self._ioc_logfile is not None: _LOGGER.debug("VA: Cleanup: close IOC log file") self._ioc_logfile.close() self._ioc_logfile = None else: _LOGGER.debug("VA: Cleanup: IOC log file is NONE") if self._rm_work_dir: _LOGGER.debug("VA: Cleanup: remove work directory") shutil.rmtree(self.work_dir) else: _LOGGER.debug("VA: Cleanup: work directory is NONE") self._started = False self._continue = False if execute_error is None: self._wait_event.Signal() else: self._wait_event.SignalException(execute_error)
def __init__(self, at_lattice, callback=None, emit_calc=True): """ .. Note:: To avoid errors, the physics data must be initially calculated here, during creation, otherwise it could be accidentally referenced before the attributes _emitdata and _lindata exist due to delay between class creation and the end of the first calculation in the thread. Args: at_lattice (at.lattice_object.Lattice): An instance of an AT lattice object. callback (callable): Optional, if passed it is called on completion of each round of physics calculations. emit_calc (bool): Whether or not to perform the beam envelope based emittance calculations. **Methods:** """ if (not callable(callback)) and (callback is not None): raise TypeError("If passed, 'callback' should be callable, {0} is " "not.".format(callback)) self._at_lat = at_lattice self._rp = numpy.ones(len(at_lattice) + 1, dtype=bool) self._emit_calc = emit_calc # Initial phys data calculation. if self._emit_calc: self._at_lat.radiation_on() self._emitdata = self._at_lat.ohmi_envelope(self._rp) self._at_lat.radiation_off() self._lindata = self._at_lat.linopt(refpts=self._rp, get_chrom=True, coupled=False) self._radint = self._at_lat.get_radiation_integrals( 0.0, self._lindata[3]) # Threading stuff initialisation. self._queue = cothread.EventQueue() # Explicitly manage the cothread Events, so turn off auto_reset. self._paused = cothread.Event(auto_reset=False) self.up_to_date = cothread.Event(auto_reset=False) self.up_to_date.Signal() self._calculation_thread = cothread.Spawn(self._recalculate_phys_data, callback)
def test_server_makefile(self): """Test makefile() with socket() which behaves the same as plain socketpair() in python 3.X """ A = socket.socket() A.bind(('localhost', 0)) A.listen(1) B = socket.socket() B.bind(('localhost', 0)) Sname = A.getsockname() Cname = B.getsockname() def server(): C, peer = A.accept() self.assertEqual(peer, Cname) F = C.makefile(mode='w') C.close() F.write('hello') F.close() server = cothread.Spawn(server, raise_on_wait=True) try: B.connect(Sname) fB = B.makefile(mode='r') B.close() msg = fB.readline() fB.close() except socket.error: # ensure we capture server exceptions... server.Wait(1.0) raise # only get here if no server exception else: server.Wait(1.0) A.close() self.assertEqual(msg, 'hello')
def test_txrx(self): "Check that we can actually send/recv bewtween cothreads" A, B = socket.socketpair() def tx(): for i in range(10): A.send(chr(i)) A.close() tx = cothread.Spawn(tx, raise_on_wait=True) data = b'' while True: c = B.recv(100) if not c: break data += c B.close() tx.Wait(1.0) self.assertEqual(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09', data)
def __init__(self): self.q = cothread.EventQueue() cothread.Spawn(self.run)
def process_request(self, request, client_address): cothread.Spawn(self.process_request_thread, request, client_address)