async def test_cancellable_wait_cancels_subtasks_when_cancelled(event_loop):
    token = CancelToken("")
    future = asyncio.ensure_future(token.cancellable_wait(asyncio.sleep(2)))
    with pytest.raises(asyncio.TimeoutError):
        # asyncio.wait_for() will timeout and then cancel our cancellable_wait() future, but
        # Task.cancel() doesn't immediately cancels the task
        # (https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel), so we need
        # the sleep below before we check that the task is actually cancelled.
        await asyncio.wait_for(future, timeout=0.01)
    await asyncio.sleep(0)
    assert future.cancelled()
    await assert_only_current_task_not_done()
def test_token_chain_trigger_chain():
    token = CancelToken("token")
    token2 = CancelToken("token2")
    token3 = CancelToken("token3")
    intermediate_chain = token.chain(token2)
    chain = intermediate_chain.chain(token3)
    assert not chain.triggered
    chain.trigger()
    assert chain.triggered
    assert not intermediate_chain.triggered
    assert chain.triggered_token == chain
    assert not token.triggered
    assert not token2.triggered
    assert not token3.triggered
async def test_wait_cancel_pending_tasks_on_cancellation(event_loop):
    """Test that cancelling a pending CancelToken.wait() coroutine doesn't leave .wait()
    coroutines for any chained tokens behind.
    """
    token = (
        CancelToken("token").chain(CancelToken("token2")).chain(CancelToken("token3"))
    )
    token_wait_coroutine = token.wait()
    done, pending = await asyncio.wait([token_wait_coroutine], timeout=0.1)
    assert len(done) == 0
    assert len(pending) == 1
    pending_task = pending.pop()
    assert pending_task._coro == token_wait_coroutine
    pending_task.cancel()
    await assert_only_current_task_not_done()
Esempio n. 4
0
    def __init__(self, env, master_server, loop):
        self.loop = loop
        self.env = env
        self.master_server = master_server
        master_server.network = self  # cannot say this is a good design

        self.cancel_token = CancelToken("p2pserver")
        if env.cluster_config.P2P.BOOT_NODES:
            bootstrap_nodes = env.cluster_config.P2P.BOOT_NODES.split(",")
        else:
            bootstrap_nodes = []
        if env.cluster_config.P2P.PRIV_KEY:
            privkey = keys.PrivateKey(bytes.fromhex(env.cluster_config.P2P.PRIV_KEY))
        else:
            privkey = ecies.generate_privkey()

        self.server = QuarkServer(
            privkey=privkey,
            port=env.cluster_config.P2P_PORT,
            network_id=env.cluster_config.P2P.NETWORK_ID,
            bootstrap_nodes=tuple(
                [kademlia.Node.from_uri(enode) for enode in bootstrap_nodes]
            ),
            token=self.cancel_token,
            upnp=env.cluster_config.P2P.UPNP,
        )
Esempio n. 5
0
def get_discovery_protocol(seed=b"seed", address=None):
    privkey = keys.PrivateKey(keccak(seed))
    if address is None:
        address = random_address()
    return discovery.DiscoveryProtocol(
        privkey, address, [], CancelToken("discovery-test")
    )
Esempio n. 6
0
def main():
    Logger.set_logging_level("debug")
    loop = asyncio.get_event_loop()
    loop.set_debug(True)

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--bootnode",
        default="enode://c571e0db93d17cc405cb57640826b70588a6a28785f38b21be471c609ca12fcb06cb306ac44872908f5bed99046031a5af82072d484e3ef9029560c1707193a0@127.0.0.1:29000",
        type=str,
    )
    parser.add_argument("--listen_host", default="127.0.0.1", type=str)
    parser.add_argument(
        "--listen_port",
        default=29000,
        help="port for discovery UDP and P2P TCP connection",
        type=int,
    )
    parser.add_argument("--max_peers", default=10, type=int)
    # private key of the bootnode above is 31552f186bf90908ce386fb547dd0410bf443309125cc43fd0ffd642959bf6d9
    parser.add_argument(
        "--privkey",
        default="",
        help="hex string of private key; if empty, will be auto-generated",
        type=str,
    )

    args = parser.parse_args()

    if args.privkey:
        privkey = keys.PrivateKey(bytes.fromhex(args.privkey))
    else:
        privkey = ecies.generate_privkey()
    addr = kademlia.Address(args.listen_host, args.listen_port, args.listen_port)
    bootstrap_nodes = tuple([kademlia.Node.from_uri(args.bootnode)])

    cancel_token = CancelToken("discovery")
    discovery = DiscoveryProtocol(privkey, addr, bootstrap_nodes, cancel_token)

    async def run() -> None:
        await loop.create_datagram_endpoint(
            lambda: discovery, local_addr=("0.0.0.0", args.listen_port)
        )
        try:
            await discovery.bootstrap()
            while True:
                Logger.info("Routing table size={}".format(len(discovery.routing)))
                await cancel_token.cancellable_wait(asyncio.sleep(5))
        except OperationCancelled:
            pass
        finally:
            await discovery.stop()

    for sig in [signal.SIGINT, signal.SIGTERM]:
        loop.add_signal_handler(sig, cancel_token.trigger)

    loop.run_until_complete(run())
    loop.close()
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--privkey",
        default="",
        help="hex string of private key; if empty, will be auto-generated",
        type=str,
    )
    parser.add_argument(
        "--listen_port",
        default=29000,
        help="port for discovery UDP and P2P TCP connection",
        type=int,
    )
    parser.add_argument("--logging_level", default="info", type=str)
    args = parser.parse_args()

    Logger.set_logging_level(args.logging_level)

    if args.privkey:
        privkey = keys.PrivateKey(bytes.fromhex(args.privkey))
    else:
        privkey = ecies.generate_privkey()

    cancel_token = CancelToken("server")
    server = ParagonServer(
        privkey=privkey,
        port=args.listen_port,
        network_id=NETWORK_ID,
        token=cancel_token,
    )

    loop = asyncio.get_event_loop()
    loop.set_debug(True)

    for sig in [signal.SIGINT, signal.SIGTERM]:
        loop.add_signal_handler(sig, cancel_token.trigger)

    loop.run_until_complete(server.run())
    loop.run_until_complete(server.cancel())
    loop.close()
def test_token_chain_event_loop_mismatch():
    token = CancelToken("token")
    token2 = CancelToken("token2", loop=asyncio.new_event_loop())
    with pytest.raises(EventLoopMismatch):
        token.chain(token2)
async def test_cancellable_wait_operation_cancelled(event_loop):
    token = CancelToken("token")
    token.trigger()
    with pytest.raises(OperationCancelled):
        await token.cancellable_wait(asyncio.sleep(0.02))
    await assert_only_current_task_not_done()
Esempio n. 10
0
def test_token_single():
    token = CancelToken("token")
    assert not token.triggered
    token.trigger()
    assert token.triggered
    assert token.triggered_token == token