Example #1
0
def optschain(config, symbol, date, tl, rate, test):
    """Start an option chain UI
    """
    # global opts
    loglevel = config['loglevel']
    brokername = config['broker']

    _kivy_import_hack()
    from .kivy.option_chain import _async_main

    async def main(tries):
        async with maybe_spawn_brokerd(tries=tries, loglevel=loglevel):
            # run app "main"
            await _async_main(
                symbol,
                brokername,
                rate=rate,
                loglevel=loglevel,
                test=test,
            )

    tractor.run(
        partial(main, tries=1),
        name='kivy-options-chain',
        loglevel=loglevel if tl else None,
        start_method='forkserver',
    )
Example #2
0
File: cli.py Project: pikers/piker
def optschain(config, symbol, date, rate, test):
    """Start an option chain UI
    """
    # global opts
    loglevel = config['loglevel']
    brokername = config['broker']

    _kivy_import_hack()
    from .kivy.option_chain import _async_main

    async def main():
        async with maybe_spawn_brokerd(loglevel=loglevel):
            # run app "main"
            await _async_main(
                symbol,
                brokername,
                rate=rate,
                loglevel=loglevel,
                test=test,
            )

    tractor.run(
        main,
        name='kivy-options-chain',
    )
Example #3
0
def ingest(config, name, test_file, tl, url):
    """Ingest real-time broker quotes and ticks to a marketstore instance.
    """
    # global opts
    brokermod = config['brokermod']
    loglevel = config['loglevel']
    tractorloglevel = config['tractorloglevel']
    # log = config['log']

    watchlist_from_file = wl.ensure_watchlists(config['wl_path'])
    watchlists = wl.merge_watchlist(watchlist_from_file, wl._builtins)
    symbols = watchlists[name]

    tractor.run(
        partial(
            ingest_quote_stream,
            symbols,
            brokermod.name,
            tries=1,
            loglevel=loglevel,
        ),
        name='ingest_marketstore',
        loglevel=tractorloglevel,
        debug_mode=True,
    )
Example #4
0
def test_remote_error(arb_addr, args_err):
    """Verify an error raised in a subactor that is propagated
    to the parent nursery, contains the underlying boxed builtin
    error type info and causes cancellation and reraising all the
    way up the stack.
    """
    args, errtype = args_err

    async def main():
        async with tractor.open_nursery() as nursery:

            portal = await nursery.run_in_actor('errorer', assert_err, **args)

            # get result(s) from main task
            try:
                await portal.result()
            except tractor.RemoteActorError as err:
                assert err.type == errtype
                print("Look Maa that actor failed hard, hehh")
                raise

    with pytest.raises(tractor.RemoteActorError) as excinfo:
        tractor.run(main, arbiter_addr=arb_addr)

    # ensure boxed error is correct
    assert excinfo.value.type == errtype
Example #5
0
def ms_destroy(config: dict, names: List[str], url: str) -> None:
    """Destroy symbol entries in the local marketstore instance.
    """
    async def main():
        nonlocal names
        async with get_client(url) as client:

            if not names:
                names = await client.list_symbols()

            # default is to wipe db entirely.
            answer = input(
                "This will entirely wipe you local marketstore db @ "
                f"{url} of the following symbols:\n {pformat(names)}"
                "\n\nDelete [N/y]?\n")

            if answer == 'y':
                for sym in names:
                    # tbk = _tick_tbk.format(sym)
                    tbk = tuple(sym, *_tick_tbk_ids)
                    print(f"Destroying {tbk}..")
                    await client.destroy(mk_tbk(tbk))
            else:
                print("Nothing deleted.")

    tractor.run(main)
Example #6
0
def test_loglevel_propagated_to_subactor(
    start_method,
    capfd,
    arb_addr,
):
    if start_method == 'forkserver':
        pytest.skip(
            "a bug with `capfd` seems to make forkserver capture not work?")

    level = 'critical'

    async def main():
        async with tractor.open_nursery() as tn:
            await tn.run_in_actor(
                'log_checker',
                check_loglevel,
                level=level,
            )

    tractor.run(
        main,
        name='arbiter',
        loglevel=level,
        start_method=start_method,
        arbiter_addr=arb_addr,
    )
    # ensure subactor spits log message on stderr
    captured = capfd.readouterr()
    assert 'yoyoyo' in captured.err
Example #7
0
def optschain(config, symbol, date, tl, rate, test):
    """Start the real-time option chain UI.
    """
    # global opts
    loglevel = config['loglevel']
    brokername = config['broker']

    from .ui.option_chain import _async_main

    async def main(tries):
        async with maybe_spawn_brokerd_as_subactor(
                tries=tries, loglevel=loglevel) as portal:
            # run app "main"
            await _async_main(
                symbol,
                brokername,
                rate=rate,
                loglevel=loglevel,
                test=test,
            )

    tractor.run(
        partial(main, tries=1),
        name='kivy-options-chain',
        loglevel=loglevel if tl else None,
    )
Example #8
0
def test_stream_from_single_subactor(arb_addr, start_method):
    """Verify streaming from a spawned async generator.
    """
    tractor.run(
        stream_from_single_subactor,
        arbiter_addr=arb_addr,
        start_method=start_method,
    )
Example #9
0
def ms_shell(config, name, tl, url):
    """Start an IPython shell ready to query the local marketstore db.
    """
    async def main():
        async with get_client(url) as client:
            query = client.query  # noqa
            # TODO: write magics to query marketstore
            from IPython import embed
            embed()

    tractor.run(main)
Example #10
0
def test_register_duplicate_name(daemon, arb_addr):
    async def main():
        assert not tractor.current_actor().is_arbiter
        async with tractor.open_nursery() as n:
            p1 = await n.start_actor('doggy')
            p2 = await n.start_actor('doggy')

            async with tractor.wait_for_actor('doggy') as portal:
                assert portal.channel.uid in (p2.channel.uid, p1.channel.uid)

            await n.cancel()

    # run it manually since we want to start **after**
    # the other "daemon" program
    tractor.run(main, arbiter_addr=arb_addr)
Example #11
0
def record(config, rate, name, dhost, filename):
    """Record client side quotes to a file on disk
    """
    # global opts
    brokermod = config['brokermod']
    loglevel = config['loglevel']
    log = config['log']

    watchlist_from_file = wl.ensure_watchlists(_watchlists_data_path)
    watchlists = wl.merge_watchlist(watchlist_from_file, wl._builtins)
    tickers = watchlists[name]
    if not tickers:
        log.error(f"No symbols found for watchlist `{name}`?")
        return

    async def main(tries):
        async with maybe_spawn_brokerd(
            tries=tries, loglevel=loglevel
        ) as portal:
            # run app "main"
            return await data.stream_to_file(
                name, filename,
                portal, tickers,
                brokermod, rate,
            )

    filename = tractor.run(partial(main, tries=1), name='data-feed-recorder')
    click.echo(f"Data feed recording saved to {filename}")
Example #12
0
def time_quad_ex(arb_addr):
    timeout = 7 if platform.system() == 'Windows' else 3
    start = time.time()
    results = tractor.run(cancel_after, timeout, arbiter_addr=arb_addr)
    diff = time.time() - start
    assert results
    return results, diff
Example #13
0
def test_not_fast_enough_quad(arb_addr, time_quad_ex, cancel_delay):
    """Verify we can cancel midway through the quad example and all actors
    cancel gracefully.
    """
    results, diff = time_quad_ex
    delay = max(diff - cancel_delay, 0)
    results = tractor.run(cancel_after, delay, arbiter_addr=arb_addr)
    assert results is None
Example #14
0
def services(config, tl, names):
    async def list_services():
        async with tractor.get_arbiter(
                *tractor.current_actor()._arb_addr) as portal:
            registry = await portal.run('self', 'get_registry')
            json_d = {}
            for uid, socket in registry.items():
                name, uuid = uid
                host, port = socket
                json_d[f'{name}.{uuid}'] = f'{host}:{port}'
            click.echo(f"Available `piker` services:\n{colorize_json(json_d)}")

    tractor.run(
        list_services,
        name='service_query',
        loglevel=config['loglevel'] if tl else None,
    )
Example #15
0
def test_local_arbiter_subactor_global_state(arb_addr):
    result = tractor.run(
        spawn,
        True,
        name='arbiter',
        statespace=statespace,
        arbiter_addr=arb_addr,
    )
    assert result == 10
Example #16
0
def test_cancel_single_subactor(arb_addr):
    """Ensure a ``ActorNursery.start_actor()`` spawned subactor
    cancels when the nursery is cancelled.
    """
    async def spawn_actor():
        """Spawn an actor that blocks indefinitely.
        """
        async with tractor.open_nursery() as nursery:

            portal = await nursery.start_actor(
                'nothin',
                rpc_module_paths=[__name__],
            )
            assert (await portal.run(__name__, 'do_nothing')) is None

            # would hang otherwise
            await nursery.cancel()

    tractor.run(spawn_actor, arbiter_addr=arb_addr)
Example #17
0
def test_local_actor_async_func(arb_addr):
    """Verify a simple async function in-process.
    """
    nums = []

    async def print_loop():
        # arbiter is started in-proc if dne
        assert tractor.current_actor().is_arbiter

        for i in range(10):
            nums.append(i)
            await trio.sleep(0.1)

    start = time.time()
    tractor.run(print_loop, arbiter_addr=arb_addr)

    # ensure the sleeps were actually awaited
    assert time.time() - start >= 1
    assert nums == list(range(10))
Example #18
0
def services(config, tl, names):

    async def list_services():

        async with tractor.get_arbiter(
            *_tractor_kwargs['arbiter_addr']
        ) as portal:
            registry = await portal.run_from_ns('self', 'get_registry')
            json_d = {}
            for key, socket in registry.items():
                # name, uuid = uid
                host, port = socket
                json_d[key] = f'{host}:{port}'
            click.echo(f"{colorize_json(json_d)}")

    tractor.run(
        list_services,
        name='service_query',
        loglevel=config['loglevel'] if tl else None,
        arbiter_addr=_tractor_kwargs['arbiter_addr'],
    )
Example #19
0
def test_multierror_fast_nursery(arb_addr, start_method, num_subactors, delay):
    """Verify we raise a ``trio.MultiError`` out of a nursery where
    more then one actor errors and also with a delay before failure
    to test failure during an ongoing spawning.
    """
    async def main():
        async with tractor.open_nursery() as nursery:
            for i in range(num_subactors):
                await nursery.run_in_actor(f'errorer{i}',
                                           assert_err,
                                           delay=delay)

    with pytest.raises(trio.MultiError) as exc_info:
        tractor.run(main, arbiter_addr=arb_addr)

    assert exc_info.type == tractor.MultiError
    err = exc_info.value
    assert len(err.exceptions) == num_subactors
    for exc in err.exceptions:
        assert isinstance(exc, tractor.RemoteActorError)
        assert exc.type == AssertionError
Example #20
0
def test_single_subactor_pub_multitask_subs(
    loglevel,
    arb_addr,
):
    async def main():

        async with tractor.open_nursery() as n:

            portal = await n.start_actor(
                'streamer',
                rpc_module_paths=[__name__],
            )
            async with tractor.wait_for_actor('streamer'):
                # block until 2nd actor is initialized
                pass

            async with trio.open_nursery() as tn:
                agen = await tn.start(subs, ['even'], 'streamer')

                await trio.sleep(0.1)
                tn.start_soon(subs, ['even'], 'streamer')

                # XXX this will trigger the python bug:
                # https://bugs.python.org/issue32526
                # if using async generators to wrap tractor channels
                await agen.aclose()

                await trio.sleep(0.1)
                tn.start_soon(subs, ['even'], 'streamer')
                await trio.sleep(0.1)
                tn.start_soon(subs, ['even'], 'streamer')

            await portal.cancel_actor()

    tractor.run(
        main,
        arbiter_addr=arb_addr,
        rpc_module_paths=[__name__],
    )
Example #21
0
def monitor(config, rate, name, dhost, test, tl):
    """Start a real-time watchlist UI
    """
    # global opts
    brokermod = config['brokermod']
    loglevel = config['loglevel']
    log = config['log']

    watchlist_from_file = wl.ensure_watchlists(_watchlists_data_path)
    watchlists = wl.merge_watchlist(watchlist_from_file, wl._builtins)
    tickers = watchlists[name]
    if not tickers:
        log.error(f"No symbols found for watchlist `{name}`?")
        return

    _kivy_import_hack()
    from .kivy.monitor import _async_main

    async def main(tries):
        async with maybe_spawn_brokerd(brokername=brokermod.name,
                                       tries=tries,
                                       loglevel=loglevel) as portal:
            # run app "main"
            await _async_main(
                name,
                portal,
                tickers,
                brokermod,
                rate,
                test=test,
            )

    tractor.run(
        partial(main, tries=1),
        name='monitor',
        loglevel=loglevel if tl else None,
        rpc_module_paths=['piker.ui.kivy.monitor'],
        start_method='forkserver',
    )
Example #22
0
def test_multierror(arb_addr):
    """Verify we raise a ``trio.MultiError`` out of a nursery where
    more then one actor errors.
    """
    async def main():
        async with tractor.open_nursery() as nursery:

            await nursery.run_in_actor('errorer1', assert_err)
            portal2 = await nursery.run_in_actor('errorer2', assert_err)

            # get result(s) from main task
            try:
                await portal2.result()
            except tractor.RemoteActorError as err:
                assert err.type == AssertionError
                print("Look Maa that first actor failed hard, hehh")
                raise

        # here we should get a `trio.MultiError` containing exceptions
        # from both subactors

    with pytest.raises(trio.MultiError):
        tractor.run(main, arbiter_addr=arb_addr)
Example #23
0
def test_not_fast_enough_quad(arb_addr, time_quad_ex, cancel_delay):
    """Verify we can cancel midway through the quad example and all actors
    cancel gracefully.
    """
    results, diff = time_quad_ex
    delay = max(diff - cancel_delay, 0)
    results = tractor.run(cancel_after, delay, arbiter_addr=arb_addr)
    if platform.system() == 'Windows' and results is not None:
        # In Windows CI it seems later runs are quicker then the first
        # so just ignore these
        print("Woa there windows caught your breath eh?")
    else:
        # should be cancelled mid-streaming
        assert results is None
Example #24
0
def ingest(config, name, test_file, tl):
    '''
    Ingest real-time broker quotes and ticks to a marketstore instance.

    '''
    # global opts
    loglevel = config['loglevel']
    tractorloglevel = config['tractorloglevel']
    # log = config['log']

    watchlist_from_file = wl.ensure_watchlists(config['wl_path'])
    watchlists = wl.merge_watchlist(watchlist_from_file, wl._builtins)
    symbols = watchlists[name]

    grouped_syms = {}
    for sym in symbols:
        symbol, _, provider = sym.rpartition('.')
        if provider not in grouped_syms:
            grouped_syms[provider] = []

        grouped_syms[provider].append(symbol)

    async def entry_point():
        async with tractor.open_nursery() as n:
            for provider, symbols in grouped_syms.items(): 
                await n.run_in_actor(
                    ingest_quote_stream,
                    name='ingest_marketstore',
                    symbols=symbols,
                    brokername=provider,
                    tries=1,
                    actorloglevel=loglevel,
                    loglevel=tractorloglevel
                )

    tractor.run(entry_point)
Example #25
0
def search(config, pattern):
    """Search for symbols from broker backend(s).
    """
    # global opts
    brokermod = config['brokermod']

    quotes = tractor.run(
        partial(core.symbol_search, brokermod, pattern),
        start_method='forkserver',
        loglevel='info',
    )
    if not quotes:
        log.error(f"No matches could be found for {pattern}?")
        return

    click.echo(colorize_json(quotes))
Example #26
0
# this is the main actor and *arbiter*
async def main():
    # a nursery which spawns "actors"
    async with tractor.open_nursery() as nursery:

        seed = int(1e3)
        import time
        pre_start = time.time()

        portal = await nursery.run_in_actor(
            'aggregator',
            aggregate,
            seed=seed,
        )

        start = time.time()
        # the portal call returns exactly what you'd expect
        # as if the remote "aggregate" function was called locally
        result_stream = []
        async for value in await portal.result():
            result_stream.append(value)

        print(f"STREAM TIME = {time.time() - start}")
        print(f"STREAM + SPAWN TIME = {time.time() - pre_start}")
        assert result_stream == list(range(seed))
        return result_stream


if __name__ == '__main__':
    final_stream = tractor.run(main, arbiter_addr=('127.0.0.1', 1616))
Example #27
0
def test_multi_actor_subs_arbiter_pub(
    loglevel,
    arb_addr,
    pub_actor,
):
    """Try out the neato @pub decorator system.
    """
    async def main():
        ss = tractor.current_actor().statespace

        async with tractor.open_nursery() as n:

            name = 'arbiter'

            if pub_actor == 'streamer':
                # start the publisher as a daemon
                master_portal = await n.start_actor(
                    'streamer',
                    rpc_module_paths=[__name__],
                )

            even_portal = await n.run_in_actor('evens',
                                               subs,
                                               which=['even'],
                                               pub_actor_name=name)
            odd_portal = await n.run_in_actor('odds',
                                              subs,
                                              which=['odd'],
                                              pub_actor_name=name)

            async with tractor.wait_for_actor('evens'):
                # block until 2nd actor is initialized
                pass

            if pub_actor == 'arbiter':
                # wait for publisher task to be spawned in a local RPC task
                while not ss.get('get_topics'):
                    await trio.sleep(0.1)

                get_topics = ss.get('get_topics')

                assert 'even' in get_topics()

            async with tractor.wait_for_actor('odds'):
                # block until 2nd actor is initialized
                pass

            if pub_actor == 'arbiter':
                start = time.time()
                while 'odd' not in get_topics():
                    await trio.sleep(0.1)
                    if time.time() - start > 1:
                        pytest.fail("odds subscription never arrived?")

            # TODO: how to make this work when the arbiter gets
            # a portal to itself? Currently this causes a hang
            # when the channel server is torn down due to a lingering
            # loopback channel
            #     with trio.move_on_after(1):
            #         await subs(['even', 'odd'])

            # XXX: this would cause infinite
            # blocking due to actor never terminating loop
            # await even_portal.result()

            await trio.sleep(0.5)
            await even_portal.cancel_actor()
            await trio.sleep(0.5)

            if pub_actor == 'arbiter':
                assert 'even' not in get_topics()

            await odd_portal.cancel_actor()
            await trio.sleep(1)

            if pub_actor == 'arbiter':
                while get_topics():
                    await trio.sleep(0.1)
                    if time.time() - start > 1:
                        pytest.fail("odds subscription never dropped?")
            else:
                await master_portal.cancel_actor()

    tractor.run(
        main,
        arbiter_addr=arb_addr,
        rpc_module_paths=[__name__],
    )
Example #28
0
 def run():
     tractor.run(
         main,
         arbiter_addr=arb_addr,
         rpc_module_paths=exposed_mods,
     )
Example #29
0
def test_no_main():
    """An async function **must** be passed to ``tractor.run()``.
    """
    with pytest.raises(TypeError):
        tractor.run(None)
Example #30
0
import tractor

tractor.log.get_console_log("INFO")


async def main(service_name):

    async with tractor.open_nursery() as an:
        await an.start_actor(service_name)

        async with tractor.get_arbiter('127.0.0.1', 1616) as portal:
            print(f"Arbiter is listening on {portal.channel}")

        async with tractor.wait_for_actor(service_name) as sockaddr:
            print(f"my_service is found at {sockaddr}")

        await an.cancel()


if __name__ == '__main__':
    tractor.run(main, 'some_actor_name')