Example #1
0
 async def _call_func(self, func, args, kwargs):
     try:
         retval = await func(*args, **kwargs)
     except BaseException as exc:
         self._result_queue.append(Error(exc))
     else:
         self._result_queue.append(Value(retval))
Example #2
0
 async def _recv_pong(self) -> None:
     try:
         cancelled, task = self._pings.popleft()
     except IndexError as ex:
         raise exception.UnexpectedPong() from ex
     if not cancelled:
         trio.hazmat.reschedule(task, Value(None))
Example #3
0
 async def _recv_ack(self) -> None:
     msg_id, = await self.stream.recv_struct('>L')
     try:
         cancelled, task = self._message_ids.pop(msg_id)
     except KeyError as ex:
         raise exception.UnexpectedAck(msg_id) from ex
     if not cancelled:
         trio.hazmat.reschedule(task, Value(None))
Example #4
0
 async def _call_func(self, func: Callable[..., Awaitable[object]],
                      args: tuple, kwargs: dict) -> None:
     try:
         retval = await func(*args, **kwargs)
     except BaseException as exc:
         self._result_queue.append(Error(exc))
     else:
         self._result_queue.append(Value(retval))
Example #5
0
def test_Outcome():
    v = Value(1)
    assert v.value == 1
    assert v.unwrap() == 1
    assert repr(v) == "Value(1)"

    with pytest.raises(AlreadyUsedError):
        v.unwrap()

    v = Value(1)

    exc = RuntimeError("oops")
    e = Error(exc)
    assert e.error is exc
    with pytest.raises(RuntimeError):
        e.unwrap()
    with pytest.raises(AlreadyUsedError):
        e.unwrap()
    assert repr(e) == f"Error({exc!r})"

    e = Error(exc)
    with pytest.raises(TypeError):
        Error("hello")
    with pytest.raises(TypeError):
        Error(RuntimeError)

    def expect_1():
        assert (yield) == 1
        yield "ok"

    it = iter(expect_1())
    next(it)
    assert v.send(it) == "ok"
    with pytest.raises(AlreadyUsedError):
        v.send(it)

    def expect_RuntimeError():
        with pytest.raises(RuntimeError):
            yield
        yield "ok"

    it = iter(expect_RuntimeError())
    next(it)
    assert e.send(it) == "ok"
    with pytest.raises(AlreadyUsedError):
        e.send(it)
Example #6
0
    async def _recv_data_any(self, msg_id, data_type, plen):
        if plen >= self.max_data:
            raise exception.LimitBreached('Peer tried to send us {} bytes, limit is {}'.format(plen, self.max_data))

        payload = await self.stream.recv_exactly(plen)
        data = Data(self, msg_id, data_type, payload)
        if not self._recv_data_task:
            raise Exception('Was not expecting any data')
        trio.hazmat.reschedule(self._recv_data_task, Value(data))
        self._recv_data_task = None
        await data._unblock.wait()
Example #7
0
def test_Outcome_eq_hash():
    v1 = Value(["hello"])
    v2 = Value(["hello"])
    v3 = Value("hello")
    v4 = Value("hello")
    assert v1 == v2
    assert v1 != v3
    with pytest.raises(TypeError):
        {v1}
    assert {v3, v4} == {v3}

    # exceptions in general compare by identity
    exc1 = RuntimeError("oops")
    exc2 = KeyError("foo")
    e1 = Error(exc1)
    e2 = Error(exc1)
    e3 = Error(exc2)
    e4 = Error(exc2)
    assert e1 == e2
    assert e3 == e4
    assert e1 != e3
    assert {e1, e2, e3, e4} == {e1, e3}
Example #8
0
def cutin_nowait(self, value):
    if self._closed:
        raise trio.ClosedResourceError
    if self._state.open_receive_channels == 0:
        raise trio.BrokenResourceError
    if self._state.receive_tasks:
        assert not self._state.data
        task, _ = self._state.receive_tasks.popitem(last=False)
        task.custom_sleep_data._tasks.remove(task)
        trio.lowlevel.reschedule(task, Value(value))
    elif len(self._state.data) < self._state.max_buffer_size:
        self._state.data.appendleft(value)
    else:
        raise trio.WouldBlock
Example #9
0
 def put_nowait(self, value):
     if self.closed:
         raise _core.ClosedResourceError
     if not self._buf.get_channels:
         raise BrokenChannelError
     if self._buf.get_tasks:
         assert not self._buf.data
         task, _ = self._buf.get_tasks.popitem(last=False)
         task.custom_sleep_data._tasks.remove(task)
         _core.reschedule(task, Value(value))
     elif len(self._buf.data) < self._buf.capacity:
         self._buf.data.append(value)
     else:
         raise _core.WouldBlock
Example #10
0
async def test_acapture():
    async def add(x, y):
        await asyncio.sleep(0)
        return x + y

    v = await outcome.acapture(add, 3, y=4)
    assert v == Value(7)

    async def raise_ValueError(x):
        await asyncio.sleep(0)
        raise ValueError(x)

    e = await outcome.acapture(raise_ValueError, 9)
    assert type(e.error) is ValueError
    assert e.error.args == (9, )
Example #11
0
    def send_nowait(self, value):
        """Like `~trio.abc.SendChannel.send`, but if the channel's buffer is
        full, raises `WouldBlock` instead of blocking.

        """
        if self._closed:
            raise trio.ClosedResourceError
        if self._state.open_receive_channels == 0:
            raise trio.BrokenResourceError
        if self._state.receive_tasks:
            assert not self._state.data
            task, _ = self._state.receive_tasks.popitem(last=False)
            task.custom_sleep_data._tasks.remove(task)
            trio.hazmat.reschedule(task, Value(value))
        elif len(self._state.data) < self._state.max_buffer_size:
            self._state.data.append(value)
        else:
            raise trio.WouldBlock
Example #12
0
async def test_asend():
    async def my_agen_func():
        assert (yield 1) == "value"
        with pytest.raises(KeyError):
            yield 2
        yield 3

    my_agen = my_agen_func().__aiter__()
    v = Value("value")
    e = Error(KeyError())
    assert (await my_agen.asend(None)) == 1
    assert (await v.asend(my_agen)) == 2
    with pytest.raises(AlreadyUsedError):
        await v.asend(my_agen)

    assert (await e.asend(my_agen)) == 3
    with pytest.raises(AlreadyUsedError):
        await e.asend(my_agen)
    with pytest.raises(StopAsyncIteration):
        await my_agen.asend(None)
Example #13
0
async def test_asend():
    @async_generator
    async def my_agen_func():
        assert (await yield_(1)) == "value"
        with pytest.raises(KeyError):
            await yield_(2)
        await yield_(3)

    my_agen = my_agen_func().__aiter__()
    if sys.version_info < (3, 5, 2):
        my_agen = await my_agen
    v = Value("value")
    e = Error(KeyError())
    assert (await my_agen.asend(None)) == 1
    assert (await v.asend(my_agen)) == 2
    with pytest.raises(AlreadyUsedError):
        await v.asend(my_agen)

    assert (await e.asend(my_agen)) == 3
    with pytest.raises(AlreadyUsedError):
        await e.asend(my_agen)
    with pytest.raises(StopAsyncIteration):
        await my_agen.asend(None)
Example #14
0
 def process_events(self, received):
     for i in range(received):
         entry = self._events[i]
         if entry.lpCompletionKey == CKeys.AFD_POLL:
             lpo = entry.lpOverlapped
             op = self._afd_ops.pop(lpo)
             waiters = op.waiters
             if waiters.current_op is not op:
                 # Stale op, nothing to do
                 pass
             else:
                 waiters.current_op = None
                 # I don't think this can happen, so if it does let's crash
                 # and get a debug trace.
                 if lpo.Internal != 0:  # pragma: no cover
                     code = ntdll.RtlNtStatusToDosError(lpo.Internal)
                     raise_winerror(code)
                 flags = op.poll_info.Handles[0].Events
                 if waiters.read_task and flags & READABLE_FLAGS:
                     _core.reschedule(waiters.read_task)
                     waiters.read_task = None
                 if waiters.write_task and flags & WRITABLE_FLAGS:
                     _core.reschedule(waiters.write_task)
                     waiters.write_task = None
                 self._refresh_afd(op.poll_info.Handles[0].Handle)
         elif entry.lpCompletionKey == CKeys.WAIT_OVERLAPPED:
             # Regular I/O event, dispatch on lpOverlapped
             waiter = self._overlapped_waiters.pop(entry.lpOverlapped)
             overlapped = entry.lpOverlapped
             transferred = entry.dwNumberOfBytesTransferred
             info = CompletionKeyEventInfo(
                 lpOverlapped=overlapped,
                 dwNumberOfBytesTransferred=transferred)
             _core.reschedule(waiter, Value(info))
         elif entry.lpCompletionKey == CKeys.LATE_CANCEL:
             # Post made by a regular I/O event's abort_fn
             # after it failed to cancel the I/O. If we still
             # have a waiter with this lpOverlapped, we didn't
             # get the regular I/O completion and almost
             # certainly the user forgot to call
             # register_with_iocp.
             self._posted_too_late_to_cancel.remove(entry.lpOverlapped)
             try:
                 waiter = self._overlapped_waiters.pop(entry.lpOverlapped)
             except KeyError:
                 # Looks like the actual completion got here before this
                 # fallback post did -- we're in the "expected" case of
                 # too-late-to-cancel, where the user did nothing wrong.
                 # Nothing more to do.
                 pass
             else:
                 exc = _core.TrioInternalError(
                     "Failed to cancel overlapped I/O in {} and didn't "
                     "receive the completion either. Did you forget to "
                     "call register_with_iocp()?".format(waiter.name))
                 # Raising this out of handle_io ensures that
                 # the user will see our message even if some
                 # other task is in an uncancellable wait due
                 # to the same underlying forgot-to-register
                 # issue (if their CancelIoEx succeeds, we
                 # have no way of noticing that their completion
                 # won't arrive). Unfortunately it loses the
                 # task traceback. If you're debugging this
                 # error and can't tell where it's coming from,
                 # try changing this line to
                 # _core.reschedule(waiter, outcome.Error(exc))
                 raise exc
         elif entry.lpCompletionKey == CKeys.FORCE_WAKEUP:
             pass
         else:
             # dispatch on lpCompletionKey
             queue = self._completion_key_queues[entry.lpCompletionKey]
             overlapped = int(ffi.cast("uintptr_t", entry.lpOverlapped))
             transferred = entry.dwNumberOfBytesTransferred
             info = CompletionKeyEventInfo(
                 lpOverlapped=overlapped,
                 dwNumberOfBytesTransferred=transferred)
             queue.put_nowait(info)
Example #15
0
def test_Value_compare():
    assert Value(1) < Value(2)
    assert not Value(3) < Value(2)
    with pytest.raises(TypeError):
        Value(1) < Value("foo")
Example #16
0
 def set_result(self, result):
     self._outcome = Value(result)
     self._event.set()
Example #17
0
async def test_the_future():
    async with trio.open_nursery() as nursery:
        fut = run(nursery, my_fn)
        func_outcome = await fut.outcome()
        assert func_outcome == Value(7)
Example #18
0
async def test_gather():
    async with trio.open_nursery() as nursery:
        future_list = [run(nursery, my_fn) for _ in range(10)]
        joined_future = gather(nursery, future_list)
        assert await joined_future.outcome() == Value([7] * 10)
Example #19
0
 async def put(self, x):
     await self._s.send(Value(x))