def main(arguments=None): parser = argparse.ArgumentParser( description=desc, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("-v", dest="verbose", action="count", default=0, help="print verbose output") parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}") parser.add_argument("server", nargs="+", type=get_server) args = parser.parse_args(arguments) if args.verbose == 0: level = logging.ERROR elif args.verbose == 1: level = logging.INFO else: level = logging.DEBUG gvars.logger.setLevel(level) try: resource.setrlimit(resource.RLIMIT_NOFILE, (50000, 50000)) except Exception: gvars.logger.warning("Require root permission to allocate resources") kernel = curio.Kernel() try: kernel.run(multi_server(*args.server)) except Exception as e: gvars.logger.exception(str(e)) except KeyboardInterrupt: kernel.run(shutdown=True)
def curio_runner(pvdb, client, *, threaded_client=False): async def server_main(): try: ctx = caproto.curio.server.Context(pvdb) await ctx.run() except caproto.curio.server.ServerExit: print('Server exited normally') except Exception as ex: print('Server failed', ex) raise finally: print('Server exiting') async def run_server_and_client(): try: server_task = await curio.spawn(server_main) # Give this a couple tries, akin to poll_readiness. for _ in range(15): try: if threaded_client: await threaded_in_curio_wrapper(client)() else: await client() except TimeoutError: continue else: break else: raise TimeoutError(f"ioc failed to start") finally: await server_task.cancel() with curio.Kernel() as kernel: kernel.run(run_server_and_client)
def main(): parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-v', dest='verbose', action='count', default=0, help='print verbose output') parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}') parser.add_argument('server', nargs='+', type=get_server) args = parser.parse_args() global verbose verbose = args.verbose try: resource.setrlimit(resource.RLIMIT_NOFILE, (50000, 50000)) except Exception as e: print('Require root permission to allocate resources') kernel = curio.Kernel() try: kernel.run(multi_server(*args.server)) except Exception as e: traceback.print_exc() for k, v in kernel._selector.get_map().items(): print(k, v, file=sys.stderr) for conn in connections: print('|', conn, file=sys.stderr) except KeyboardInterrupt: kernel.run(shutdown=True) print()
def kernel(): kernel = curio.Kernel(log_errors=False) def handle_crash(current): raise current.exc_info[1] kernel._crash_handler = handle_crash return kernel
def test_thread_client_example(curio_server): from caproto.examples.thread_client_simple import main as example_main server_runner, prefix, caget_pvdb = curio_server @conftest.threaded_in_curio_wrapper def client(): example_main(pvname1=prefix + 'int', pvname2=prefix + 'str') with curio.Kernel() as kernel: kernel.run(server_runner, client)
def get_kernel(): try: return _locals.curio_kernel except AttributeError: _locals.curio_kernel = k = curio.Kernel() if 'CURIOMONITOR' in os.environ: m = Monitor(k) k._call_at_shutdown(m.close) return k
def test_repeater(): from caproto.asyncio.repeater import main logging.getLogger('caproto').setLevel(logging.DEBUG) logging.basicConfig() loop = asyncio.get_event_loop() def run_repeater(): asyncio.set_event_loop(loop) main() thread_repeater = threading.Thread(target=run_repeater) thread_repeater.start() threads = [thread_repeater] try: print('Waiting for the repeater to start up...') time.sleep(2) async def check_repeater(): for pv in ( "XF:31IDA-OP{Tbl-Ax:X1}Mtr.VAL", "XF:31IDA-OP{Tbl-Ax:X2}Mtr.VAL", ): data = await run_caget(pv) print(data) udp_sock = ca.bcast_socket() for i in range(3): print('Sending repeater register request ({})'.format(i + 1)) udp_sock.sendto(bytes(ca.RepeaterRegisterRequest('0.0.0.0')), ('127.0.0.1', REPEATER_PORT)) await curio.sleep(1) with curio.Kernel() as kernel: kernel.run(check_repeater) finally: print('Stopping the event loop') loop.call_soon_threadsafe(loop.stop) for th in threads: print('Joining the thread') th.join() print('Closing the event loop') loop.close() print('Setting a new event loop') # new event loop for other tests asyncio.set_event_loop(asyncio.new_event_loop()) print('Done')
def test_curio_server(): import caproto.curio.client as client from caproto.curio.server import _test as example_server kernel = curio.Kernel() called = [] async def run_client(): # Some user function to call when subscriptions receive data. def user_callback(command): print("Subscription has received data.") called.append(True) broadcaster = client.SharedBroadcaster(log_level='DEBUG') await broadcaster.register() ctx = client.Context(broadcaster, log_level='DEBUG') await ctx.search('pi') print('done searching') chan1 = await ctx.create_channel('pi') chan1.register_user_callback(user_callback) # ...and then wait for all the responses. await chan1.wait_for_connection() reading = await chan1.read() print('reading:', reading) sub_id = await chan1.subscribe() await chan1.unsubscribe(sub_id) await chan1.write((5, )) reading = await chan1.read() print('reading:', reading) await chan1.write((6, )) reading = await chan1.read() print('reading:', reading) await chan1.disconnect() await chan1.circuit.socket.close() async def task(): # os.environ['EPICS_CA_ADDR_LIST'] = '255.255.255.255' try: server_task = await curio.spawn(example_server()) await curio.sleep(1) # Give server some time to start up. await run_client() print('client is done') finally: await server_task.cancel() print('server is canceled', server_task.cancelled) # prints True print(kernel._tasks) with kernel: kernel.run(task) assert called, 'subscription not called in client' print('done')
def test_with_caput(curio_server, pv, put_value, check_value, async_put=True): curio_server, caget_pvdb = curio_server async def client(): print('* client_test', pv, 'put value', put_value, 'check value', check_value) db_entry = caget_pvdb[pv] db_old = db_entry.value data = await run_caput(pv, put_value, as_string=isinstance(db_entry, ca.ChannelChar)) db_new = db_entry.value if isinstance(db_entry, (ca.ChannelInteger, ca.ChannelDouble)): clean_func = ast.literal_eval # elif isinstance(db_entry, ca.ChannelString): # clean_func = lambda v: v.split(' ', 1)[1] else: clean_func = None if clean_func is not None: for key in ('old', 'new'): data[key] = clean_func(data[key]) print('caput data', data) print('old from db', db_old) print('new from db', db_new) print('old from caput', data['old']) print('new from caput', data['new']) # check value from database compared to value from caput output assert db_new == data['new'] # check value from database compared to value the test expects assert db_new == check_value async def task(): server_task = await curio.spawn(curio_server) try: await client() finally: await server_task.cancel() with curio.Kernel() as kernel: kernel.run(task) print('done')
def test_curio_server_and_thread_client(curio_server): from caproto.threading.client import (SharedBroadcaster, PVContext) from .conftest import threaded_in_curio_wrapper curio_server, caget_pvdb = curio_server @threaded_in_curio_wrapper def client_test(): shared_broadcaster = SharedBroadcaster() cntx = PVContext(broadcaster=shared_broadcaster, log_level='DEBUG') pv = cntx.get_pv('int') assert pv.get() == caget_pvdb['int'].value print('get', pv.get()) monitor_values = [] def callback(value=None, **kwargs): print('monitor', value) monitor_values.append(value[0]) pv.add_callback(callback) pv.put(1, wait=True) pv.put(2, wait=True) pv.put(3, wait=True) for i in range(3): if pv.get() == 3: break else: time.sleep(0.1) assert len(monitor_values) == 4 async def task(): server_task = await curio.spawn(curio_server) try: await curio.run_in_thread(client_test) await client_test.wait() finally: await server_task.cancel() with curio.Kernel() as kernel: kernel.run(task)
def bench_curio_many_connections(pv_names, *, initial_value=None, log_level='DEBUG'): kernel = curio.Kernel() async def test(): broadcaster = ca.curio.client.SharedBroadcaster(log_level=log_level) await broadcaster.register() ctx = ca.curio.client.Context(broadcaster, log_level=log_level) pvs = {} async with curio.TaskGroup() as connect_task: async with curio.TaskGroup() as search_task: for pvname in pv_names: await search_task.spawn(ctx.search, pvname) while True: res = await search_task.next_done() if res is None: break pvname = res.result await connect_task.spawn(ctx.create_channel, pvname) while True: res = await connect_task.next_done() if res is None: break curio_channel = res.result pvname = curio_channel.channel.name pvs[pvname] = curio_channel assert len(pvs) == len(pv_names) # TODO: can't successfully test as this hammers file creation; this # will be important to resolve... await curio.sleep(1) def curio_client(): kernel.run(test()) yield curio_client logger.debug('Shutting down the kernel') kernel.run(shutdown=True) logger.debug('Done')
def test_curio_server_example(prefix, run_client): import caproto.curio.client as client from caproto.ioc_examples.type_varieties import (pvdb) from caproto.curio.server import ServerExit, start_server as server_main pvdb = {prefix + key: value for key, value in pvdb.items()} pi_pv = prefix + 'int' broadcaster = client.SharedBroadcaster() ctx = client.Context(broadcaster) async def connect(): await broadcaster.register() await ctx.search(pi_pv) print('done searching') chan1 = await ctx.create_channel(pi_pv) # ...and then wait for all the responses. await chan1.wait_for_connection() return chan1 async def task(): async def server_wrapper(): try: await server_main(pvdb) except ServerExit: print('Server exited normally') try: server_task = await curio.spawn(server_wrapper) await curio.sleep(1) # Give server some time to start up. chan1 = await connect() await run_client(chan1, pvdb, ctx) await chan1.disconnect() print('client is done') finally: try: await server_task.cancel() await server_task.join() except curio.KernelExit: print('Server exited normally') with curio.Kernel() as kernel: kernel.run(task) print('done')
def test_sync_repeater(ioc): logging.getLogger('caproto').setLevel(logging.DEBUG) logging.basicConfig() async def check_repeater(): for pv in (ioc.pvs['float'], ioc.pvs['str']): data = await run_caget('curio', pv) print(data) udp_sock = ca.bcast_socket() for i in range(3): print('Sending repeater register request ({})'.format(i + 1)) udp_sock.sendto(bytes(ca.RepeaterRegisterRequest('0.0.0.0')), ('127.0.0.1', REPEATER_PORT)) await curio.sleep(1) with curio.Kernel() as kernel: kernel.run(check_repeater)
def bench_curio_get_speed(pvname, *, initial_value=None, log_level='DEBUG'): kernel = curio.Kernel() async def curio_setup(): logger.debug('Registering...') broadcaster = ca.curio.client.SharedBroadcaster(log_level=log_level) await broadcaster.register() ctx = ca.curio.client.Context(broadcaster, log_level=log_level) logger.debug('Registered') logger.debug('Searching for %s...', pvname) await ctx.search(pvname) logger.debug('... found!') chan = await ctx.create_channel(pvname) await chan.wait_for_connection() logger.debug('Connected to %s', pvname) if initial_value is not None: logger.debug('Writing initial value') await chan.write(initial_value) logger.debug('Wrote initial value') logger.debug('Init complete') return chan def curio_client(): async def get(): reading = await chan.read() if initial_value is not None: assert len(reading.data) == len(initial_value) kernel.run(get()) chan = kernel.run(curio_setup()) assert chan.channel.states[ca.CLIENT] is ca.CONNECTED, 'Not connected' yield curio_client logger.debug('Shutting down the kernel') kernel.run(shutdown=True) logger.debug('Done')
def bench_curio_get_speed(pvname, *, initial_value=None, log_level='DEBUG'): logging.getLogger('caproto').setLevel(log_level) kernel = curio.Kernel() async def curio_setup(): ctx = await get_curio_context() logger.debug('Searching for %s...', pvname) await ctx.search(pvname) logger.debug('... found!') chan = await ctx.create_channel(pvname) await chan.wait_for_connection() logger.debug('Connected to %s', pvname) if initial_value is not None: logger.debug('Writing initial value') await chan.write(initial_value, notify=True) logger.debug('Wrote initial value') logger.debug('Init complete') return chan def curio_client(): async def get(): reading = await chan.read() if initial_value is not None: assert len(reading.data) == len(initial_value) kernel.run(get()) chan = kernel.run(curio_setup()) assert chan.channel.states[ca.CLIENT] is ca.CONNECTED, 'Not connected' try: yield curio_client finally: logger.debug('Shutting down the kernel') kernel.run(shutdown=True) logger.debug('Done')
def curio_runner(pvdb, client, *, threaded_client=False): # Hide these imports so that the other fixtures are usable by other # libraries (e.g. ophyd) without the experimental dependencies. import curio import caproto.curio async def server_main(): try: ctx = caproto.curio.server.Context(pvdb) await ctx.run() except caproto.curio.server.ServerExit: logger.info('Server exited normally') except Exception as ex: logger.error('Server failed: %s %s', type(ex), ex) raise async def run_server_and_client(): try: server_task = await curio.spawn(server_main) # Give this a couple tries, akin to poll_readiness. for _ in range(15): try: if threaded_client: await threaded_in_curio_wrapper(client)() else: await client() except TimeoutError: continue else: break else: raise TimeoutError("ioc failed to start") finally: await server_task.cancel() with curio.Kernel() as kernel: kernel.run(run_server_and_client)
def bench_curio_put_speed(pvname, *, value, log_level='DEBUG'): kernel = curio.Kernel() async def curio_setup(): logger.debug('Registering...') broadcaster = ca.curio.client.SharedBroadcaster(log_level=log_level) await broadcaster.register() ctx = ca.curio.client.Context(broadcaster, log_level=log_level) logger.debug('Registered') logger.debug('Searching for %s...', pvname) await ctx.search(pvname) logger.debug('... found!') chan = await ctx.create_channel(pvname) await chan.wait_for_connection() logger.debug('Connected to %s', pvname) return chan def curio_client(): async def put(): await chan.write(value) kernel.run(put()) chan = kernel.run(curio_setup()) assert chan.channel.states[ca.CLIENT] is ca.CONNECTED, 'Not connected' yield curio_client async def check(): reading = await chan.read() np.testing.assert_array_almost_equal(reading.data, value) kernel.run(check()) logger.debug('Shutting down the kernel') kernel.run(shutdown=True) logger.debug('Done')
def bench_curio_put_speed(pvname, *, value, log_level='DEBUG'): logging.getLogger('caproto').setLevel(log_level) kernel = curio.Kernel() async def curio_setup(): ctx = await get_curio_context() logger.debug('Searching for %s...', pvname) await ctx.search(pvname) logger.debug('... found!') chan = await ctx.create_channel(pvname) await chan.wait_for_connection() logger.debug('Connected to %s', pvname) return chan def curio_client(): async def put(): await chan.write(value, notify=True) kernel.run(put()) chan = kernel.run(curio_setup()) assert chan.channel.states[ca.CLIENT] is ca.CONNECTED, 'Not connected' try: yield curio_client async def check(): reading = await chan.read() np.testing.assert_array_almost_equal(reading.data, value) kernel.run(check()) finally: logger.debug('Shutting down the kernel') kernel.run(shutdown=True) logger.debug('Done')
def _get_kernel(): global test_kernel if test_kernel is None: test_kernel = curio.Kernel() return test_kernel
def curio_client(): with curio.Kernel() as kernel: kernel.run(test)
def test_curio_server_with_caget(curio_server, pv, dbr_type): ctrl_keys = ('upper_disp_limit', 'lower_alarm_limit', 'upper_alarm_limit', 'lower_warning_limit', 'upper_warning_limit', 'lower_ctrl_limit', 'upper_ctrl_limit', 'precision') async def run_client_test(): print('* client_test', pv, dbr_type) db_entry = caget_pvdb[pv] # native type as in the ChannelData database db_native = ca.native_type(db_entry.data_type) # native type of the request req_native = ca.native_type(dbr_type) data = await run_caget(pv, dbr_type=dbr_type) print('dbr_type', dbr_type, 'data:') print(data) db_value = db_entry.value # convert from string value to enum if requesting int if (db_native == ChType.ENUM and not (req_native == ChType.STRING or dbr_type in (ChType.CTRL_ENUM, ChType.GR_ENUM))): db_value = db_entry.enum_strings.index(db_value) if req_native in (ChType.INT, ChType.LONG, ChType.SHORT, ChType.CHAR): if db_native == ChType.CHAR: assert int(data['value']) == ord(db_value) else: assert int(data['value']) == int(db_value) elif req_native in (ChType.STSACK_STRING, ): db_string_value = db_entry.alarm.alarm_string string_length = len(db_string_value) read_value = data['value'][:string_length] assert read_value == db_string_value elif req_native in (ChType.CLASS_NAME, ): assert data['class_name'] == 'caproto' elif req_native in (ChType.FLOAT, ChType.DOUBLE): assert float(data['value']) == float(db_value) elif req_native == ChType.STRING: if db_native == ChType.STRING: db_string_value = str(db_value) string_length = len(db_string_value) read_value = data['value'][:string_length] assert int(data['element_count']) == string_length assert read_value == db_string_value # due to how we monitor the caget output, we get @@@s where # null padding bytes are. so long as we verify element_count # above and the set of chars that should match, this assertion # should pass else: assert data['value'] == str(db_value) elif req_native == ChType.ENUM: bad_strings = ['Illegal Value (', 'Enum Index Overflow ('] for bad_string in bad_strings: if data['value'].startswith(bad_string): data['value'] = data['value'][len(bad_string):-1] if (db_native == ChType.ENUM and (dbr_type in (ChType.CTRL_ENUM, ChType.GR_ENUM))): # ctrl enum gets back the full string value assert data['value'] == db_value else: assert int(data['value']) == int(db_value) else: raise ValueError('TODO ' + str(dbr_type)) # TODO metadata should be cast to requested type as well! same_type = (ca.native_type(dbr_type) == db_native) if (dbr_type in ca.control_types and same_type and dbr_type != ChType.CTRL_ENUM): for key in ctrl_keys: if (key == 'precision' and ca.native_type(dbr_type) != ChType.DOUBLE): print('skipping', key) continue print('checking', key) assert float(data[key]) == getattr(db_entry, key), key if dbr_type in ca.time_types: timestamp = datetime.datetime.fromtimestamp(db_entry.timestamp) assert data['timestamp'] == timestamp if (dbr_type in ca.time_types or dbr_type in ca.status_types or dbr_type == ChType.STSACK_STRING): severity = data['severity'] if not severity.endswith('_ALARM'): severity = '{}_ALARM'.format(severity) severity = getattr(ca._dbr.AlarmSeverity, severity) assert severity == db_entry.severity, key status = data['status'] status = getattr(ca._dbr.AlarmStatus, status) assert status == db_entry.status, key if 'ackt' in data: ack_transient = data['ackt'] == 'YES' assert ack_transient == db_entry.alarm.acknowledge_transient if 'acks' in data: ack_severity = data['acks'] ack_severity = getattr(ca._dbr.AlarmSeverity, ack_severity) assert ack_severity == db_entry.alarm.acknowledge_severity async def task(): server_task = await curio.spawn(curio_server) try: await run_client_test() finally: await server_task.cancel() with curio.Kernel() as kernel: kernel.run(task) print('done')
def test_curio_client(): from caproto.curio.client import main with curio.Kernel() as kernel: kernel.run(main())
def func_wrapper(*args, **kwargs): kernel = curio.Kernel() kernel.run(func(*args, **kwargs)) kernel.run(shutdown=True)
def server_thread(context): async def server(): return await context.run(log_pv_names=True) kernel = curio.Kernel() kernel.run(server)
"target": request.target.decode("ascii"), "headers": [(name.decode("ascii"), value.decode("ascii")) for (name, value) in request.headers], "body": "", } while True: event = await wrapper.next_event() if type(event) is h11.EndOfMessage: break assert type(event) is h11.Data response_json["body"] += event.data.decode("ascii") response_body_unicode = json.dumps(response_json, sort_keys=True, indent=4, separators=(",", ": ")) response_body_bytes = response_body_unicode.encode("utf-8") await send_simple_response(wrapper, 200, "application/json; charset=utf-8", response_body_bytes) ################################################################ # Run the server ################################################################ if __name__ == "__main__": kernel = curio.Kernel() print("Listening on http://localhost:8080") kernel.run(curio.tcp_server("localhost", 8080, http_serve))
def kernel(request): """Create an instance of the default kernel for each test case.""" kernel = curio.Kernel() # request.addfinalizer(kernel.shutdown) return kernel
def test_curio_client_example(): from caproto.examples.curio_client_simple import main with curio.Kernel() as kernel: kernel.run(main())
def run(self, host, port): kernel = curio.Kernel() logging.info(f"Listening on http://{host}:{port}") kernel.run(curio.tcp_server(host, port, self.http_serve))
def kernel(request): """Create an instance of the default kernel for each test case.""" kernel = curio.Kernel() request.addfinalizer(lambda: kernel.run(shutdown=True)) return kernel
for n in range(50): total += await curio.run_cpu_bound(fib, n) except curio.CancelledError: print('Fine. Saving my work.') async def parent(): print('Parent PID', os.getpid()) kid_task = await curio.new_task(kid()) await curio.sleep(5) print("Yes, go play") await start_evt.set() await curio.SignalSet(signal.SIGHUP).wait() print("Let's go") count_task = await curio.new_task(countdown(10)) await count_task.join() print("We're leaving!") try: await kid_task.join(timeout=10) except TimeoutError: print('I warned you!') await kid_task.cancel() print("Leaving!") if __name__ == '__main__': kernel = curio.Kernel(with_monitor=True) kernel.run(parent())