예제 #1
0
파일: test_sync.py 프로젝트: sbraz/outcome
def test_capture():
    def add(x, y):
        return x + y

    v = outcome.capture(add, 2, y=3)
    assert type(v) == Value
    assert v.unwrap() == 5

    def raise_ValueError(x):
        raise ValueError(x)

    e = outcome.capture(raise_ValueError, "two")
    assert type(e) == Error
    assert type(e.error) is ValueError
    assert e.error.args == ("two",)
예제 #2
0
    def _run_sync_cb(self, q, fn, args):
        @_core.disable_ki_protection
        def unprotected_fn():
            return fn(*args)

        res = outcome.capture(unprotected_fn)
        q.put_nowait(res)
예제 #3
0
파일: _threads.py 프로젝트: teaolivia/trio
    def _run_sync_cb(self, q, fn, args):
        @disable_ki_protection
        def unprotected_fn():
            return fn(*args)

        res = outcome.capture(unprotected_fn)
        q.put_nowait(res)
예제 #4
0
파일: to_trio.py 프로젝트: matham/kivy-trio
    async def _async_callback(self, ret_func, ret_args=(), ret_kwargs=None):
        # check if canceled
        if self._gen is None:
            return

        if iscoroutinefunction(ret_func):
            with trio.CancelScope(shield=True):
                # TODO: cancel this when event is cancelled
                result = await outcome.acapture(ret_func, *ret_args,
                                                **(ret_kwargs or {}))

            assert not (hasattr(result, 'error')
                        and isinstance(result.error, trio.Cancelled))
        else:
            result = outcome.capture(ret_func, *ret_args, **(ret_kwargs or {}))

        # check if canceled
        if self._gen is None:
            return

        event = self._clock.create_lifecycle_aware_trigger(partial(
            self._kivy_callback, result),
                                                           _do_nothing,
                                                           release_ref=False)
        try:
            event()
        except ClockNotRunningError:
            pass
예제 #5
0
파일: __init__.py 프로젝트: LEW21/aioglib
 def install_fn():
     installed_set(
         capture(
             install, *[
                 _wrap_callable(arg, queue_put) if callable(arg) else arg
                 for arg in args
             ]))
예제 #6
0
파일: _threads.py 프로젝트: kaldown/trio
    def callback(q, fn, args):
        @disable_ki_protection
        def unprotected_fn():
            return fn(*args)

        res = outcome.capture(unprotected_fn)
        q.put_nowait(res)
예제 #7
0
 def _work(self):
     while True:
         if self._worker_lock.acquire(timeout=IDLE_TIMEOUT):
             # We got a job
             fn, deliver = self._job
             self._job = None
             result = outcome.capture(fn)
             # Tell the cache that we're available to be assigned a new
             # job. We do this *before* calling 'deliver', so that if
             # 'deliver' triggers a new job, it can be assigned to us
             # instead of spawning a new thread.
             self._thread_cache._idle_workers[self] = None
             deliver(result)
         else:
             # Timeout acquiring lock, so we can probably exit. But,
             # there's a race condition: we might be assigned a job *just*
             # as we're about to exit. So we have to check.
             try:
                 del self._thread_cache._idle_workers[self]
             except KeyError:
                 # Someone else removed us from the idle worker queue, so
                 # they must be in the process of assigning us a job - loop
                 # around and wait for it.
                 continue
             else:
                 # We successfully removed ourselves from the idle
                 # worker queue, so no more jobs are incoming; it's safe to
                 # exit.
                 return
예제 #8
0
파일: _threads.py 프로젝트: teaolivia/trio
 def worker_thread_fn():
     result = outcome.capture(sync_fn, *args)
     try:
         token.run_sync_soon(report_back_in_trio_thread_fn, result)
     except trio.RunFinishedError:
         # The entire run finished, so our particular task is certainly
         # long gone -- it must have cancelled.
         pass
예제 #9
0
 def worker_thread_fn():
     result = outcome.capture(sync_fn, *args)
     try:
         token.run_sync_soon(report_back_in_trio_thread_fn, result)
     except _core.RunFinishedError:
         # The entire run finished, so our particular task is certainly
         # long gone -- it must have cancelled.
         pass
예제 #10
0
파일: test_sync.py 프로젝트: sbraz/outcome
def test_traceback_frame_removal():
    def raise_ValueError(x):
        raise ValueError(x)

    e = outcome.capture(raise_ValueError, 'abc')
    with pytest.raises(ValueError) as exc_info:
        e.unwrap()
    frames = traceback.extract_tb(exc_info.value.__traceback__)
    functions = [function for _, _, function, _ in frames]
    assert functions[-2:] == ['unwrap', 'raise_ValueError']
예제 #11
0
 def _handle_job(self):
     # Handle job in a separate method to ensure user-created
     # objects are cleaned up in a consistent manner.
     fn, deliver = self._job
     self._job = None
     result = outcome.capture(fn)
     # Tell the cache that we're available to be assigned a new
     # job. We do this *before* calling 'deliver', so that if
     # 'deliver' triggers a new job, it can be assigned to us
     # instead of spawning a new thread.
     self._thread_cache._idle_workers[self] = None
     deliver(result)
예제 #12
0
파일: trio.py 프로젝트: indra8981/test
    def thread_fn(self):
        while True:
            try:
                request = self._portal.run(self._receive_from_trio.receive)
            except (Cancelled, RunFinishedError):
                break
            except trio.EndOfChannel:
                with suppress(Cancelled, RunFinishedError):
                    self._portal.run(self._send_to_trio.aclose)
                break

            response = outcome.capture(request)
            self._portal.run(self._send_to_trio.send, response)
예제 #13
0
    def report_back_in_trio_thread_fn(result):
        def do_release_then_return_result():
            # release_on_behalf_of is an arbitrary user-defined method, so it
            # might raise an error. If it does, we want that error to
            # replace the regular return value, and if the regular return was
            # already an exception then we want them to chain.
            try:
                return result.unwrap()
            finally:
                limiter.release_on_behalf_of(placeholder)

        result = outcome.capture(do_release_then_return_result)
        if task_register[0] is not None:
            _core.reschedule(task_register[0], result)
예제 #14
0
파일: _threads.py 프로젝트: sheerluck/trio
    def report_back_in_trio_thread_fn(result):
        def do_release_then_return_result():
            # release_on_behalf_of is an arbitrary user-defined method, so it
            # might raise an error. If it does, we want that error to
            # replace the regular return value, and if the regular return was
            # already an exception then we want them to chain.
            try:
                return result.unwrap()
            finally:
                limiter.release_on_behalf_of(placeholder)

        result = outcome.capture(do_release_then_return_result)
        if task_register[0] is not None:
            trio.lowlevel.reschedule(task_register[0], result)
예제 #15
0
    def thread_fn(self):
        while True:
            try:
                request = self._portal.run(self._request_queue.get)
            except Cancelled:
                continue
            except RunFinishedError:
                break

            if request is not _STOP:
                response = outcome.capture(request)
                self._portal.run(self._response_queue.put, response)
            else:
                self._portal.run(self._response_queue.put, None)
                break
예제 #16
0
    def thread_fn(self):
        while True:
            fut = asyncio.run_coroutine_threadsafe(self._request_queue.get(),
                                                   self._loop)
            try:
                request = fut.result()
            except CancelledError:
                continue

            if request.func is not None:
                request.response = outcome.capture(request.func)

                self._loop.call_soon_threadsafe(request.set_finished)
            else:
                self._loop.call_soon_threadsafe(request.set_finished)
                break
예제 #17
0
    def callback(q, fn, args):
        @disable_ki_protection
        def unprotected_fn():
            ret = fn(*args)

            if inspect.iscoroutine(ret):
                # Manually close coroutine to avoid RuntimeWarnings
                ret.close()
                raise TypeError(
                    "Trio expected a sync function, but {!r} appears to be "
                    "asynchronous".format(getattr(fn, "__qualname__", fn)))

            return ret

        res = outcome.capture(unprotected_fn)
        q.put_nowait(res)
예제 #18
0
파일: to_kivy.py 프로젝트: matham/kivy-trio
        def kivy_thread_callback_stopped(*largs):
            # This is the function that runs in the worker thread to do the
            # actual work and then schedule the calls to report back to trio
            # are we handling the callback?
            lock.setdefault(None, 0)
            # it was canceled so we have nothing to do
            if lock[None] is None:
                return

            def raise_stopped_error():
                raise EventLoopStoppedError(
                    f'async_run_in_kivy failed to complete <{func}> because '
                    f'clock stopped')

            task_container[1] = outcome.capture(raise_stopped_error)
            token.run_sync_soon(
                _report_kivy_back_in_trio_thread_fn, task_container, task)
예제 #19
0
파일: to_kivy.py 프로젝트: matham/kivy-trio
        def kivy_thread_callback(*largs):
            # This is the function that runs in the worker thread to do the
            # actual work and then schedule the calls to report back to trio
            # are we handling the callback?
            lock.setdefault(None, 0)
            # it was canceled so we have nothing to do
            if lock[None] is None:
                return

            task_container[1] = outcome.capture(func, *args, **kwargs)

            # this may raise a RunFinishedError, but
            # The entire run finished, so our particular tasks are
            # certainly long gone - this shouldn't have happened because
            # either the task should still be waiting because it wasn't
            # canceled or if it was canceled we should have returned above
            token.run_sync_soon(
                _report_kivy_back_in_trio_thread_fn, task_container, task)
예제 #20
0
파일: asyncio.py 프로젝트: indra8981/test
    def thread_fn(self):
        while True:
            fut = asyncio.run_coroutine_threadsafe(self._request_queue.get(),
                                                   self._loop)
            try:
                request = fut.result()
            except CancelledError:
                continue

            if request is not _STOP:
                response = outcome.capture(request)
                fut = asyncio.run_coroutine_threadsafe(
                    self._response_queue.put(response), self._loop)
                fut.result()
            else:
                fut = asyncio.run_coroutine_threadsafe(
                    self._response_queue.put(None), self._loop)
                fut.result()
                break
예제 #21
0
 def run_it():
     result = outcome.capture(sync_fn)
     trio_token.run_sync_soon(trio.lowlevel.reschedule, task, result)
예제 #22
0
 def capture(cls, sync_fn, *args):
     return outcome.capture(sync_fn, *args)
예제 #23
0
파일: __init__.py 프로젝트: LEW21/aioglib
def _wrap_callable(fn, wake_up):
    return lambda _, *args: wake_up(capture(fn, *args))
예제 #24
0
 def done_cb(_):
     trio.lowlevel.reschedule(task, outcome.capture(future.result))
예제 #25
0
 def abort(raise_cancel):
     result = outcome.capture(raise_cancel)
     _core.reschedule(task, result)
     return _core.Abort.FAILED
예제 #26
0
파일: _result.py 프로젝트: zezha-msft/trio
 def capture(cls, sync_fn, *args):
     return outcome.capture(sync_fn, *args)
예제 #27
0
        def is_done(_):
            nonlocal result

            result = outcome.capture(future.result)
            self.stop()
예제 #28
0
 def done_cb(_):
     trio.hazmat.reschedule(task, outcome.capture(future.result))
예제 #29
0
 def harness(x, in_q, out_q):
     result_q.put(outcome.capture(_core.run, main, x, in_q, out_q))
예제 #30
0
 def target() -> None:
     result = outcome.capture(fn)
     trio.from_thread.run_sync(send_channel.send_nowait,
                               result,
                               trio_token=trio_token)
예제 #31
0
 async def run_sync(self, sync_fn: Callable, *args) -> Optional[Outcome]:
     await trio.lowlevel.checkpoint()
     if self.retire is not _special_none_making_retire:
         return capture(lambda *a:
                        (sync_fn, args, trio.current_effective_deadline()))
예제 #32
0
 def abort(raise_cancel):
     result = outcome.capture(raise_cancel)
     _core.reschedule(task, result)
     return _core.Abort.FAILED
예제 #33
0
    def _work(recv_pipe, send_pipe, idle_timeout, init, retire):
        import inspect
        import signal

        def handle_job(job):
            fn, args = loads(job)
            ret = fn(*args)
            if inspect.iscoroutine(ret):
                # Manually close coroutine to avoid RuntimeWarnings
                ret.close()
                raise TypeError(
                    "trio-parallel worker expected a sync function, but {!r} appears "
                    "to be asynchronous".format(getattr(
                        fn, "__qualname__", fn)))

            return ret

        def safe_dumps(result):
            try:
                return dumps(result, protocol=HIGHEST_PROTOCOL)
            except BaseException as exc:
                return dumps(Error(exc), protocol=HIGHEST_PROTOCOL)

        def poll(timeout):
            deadline = time.perf_counter() + timeout
            while timeout > _abc.MAX_TIMEOUT:
                if recv_pipe.poll(_abc.MAX_TIMEOUT):
                    return True
                timeout = deadline - time.perf_counter()
            else:
                return recv_pipe.poll(timeout)

        # Intercept keyboard interrupts to avoid passing KeyboardInterrupt
        # between processes. (Trio will take charge via cancellation.)
        signal.signal(signal.SIGINT, signal.SIG_IGN)

        try:
            if isinstance(init, bytes):  # true except on "fork"
                # Signal successful startup to spawn/forkserver parents.
                send_pipe.send_bytes(ACK)
                init = loads(init)
            if isinstance(retire, bytes):  # true except on "fork"
                retire = loads(retire)
            init()
            while poll(idle_timeout):
                send_pipe.send_bytes(
                    safe_dumps(capture(handle_job, recv_pipe.recv_bytes())))
                if retire():
                    break
        except (BrokenPipeError, EOFError):
            # Graceful shutdown: If the main process closes the pipes, we will
            # observe one of these exceptions and can simply exit quietly.
            # Closing pipes manually fixed some __del__ flakiness in CI
            send_pipe.close()
            recv_pipe.close()
            return
        except BaseException:
            # Ensure BrokenWorkerError raised in the main proc.
            send_pipe.close()
            # recv_pipe must remain open and clear until the main proc closes it.
            try:
                while True:
                    recv_pipe.recv_bytes()
            except EOFError:
                pass
            raise
        else:
            # Clean idle shutdown or retirement: close recv_pipe first to minimize
            # subsequent race.
            recv_pipe.close()
            # Race condition: it is possible to sneak a write through in the main process
            # between the while loop predicate and recv_pipe.close(). Naively, this would
            # make a clean shutdown look like a broken worker. By sending a sentinel
            # value, we can indicate to a waiting main process that we have hit this
            # race condition and need a restart. However, the send MUST be non-blocking
            # to free this process's resources in a timely manner. Therefore, this message
            # can be any size on Windows but must be less than 512 bytes by POSIX.1-2001.
            send_pipe.send_bytes(dumps(None, protocol=HIGHEST_PROTOCOL))
            send_pipe.close()
예제 #34
0
 def _handle_exitstatus(self, sts):
     """This overrides an internal API of subprocess.Popen"""
     self.__result = outcome.capture(_compute_returncode, sts)