Exemplo n.º 1
0
    def test_asyncgen_hooks(self):
        old = sys.get_asyncgen_hooks()
        self.assertIsNone(old.firstiter)
        self.assertIsNone(old.finalizer)

        firstiter = lambda *a: None
        sys.set_asyncgen_hooks(firstiter=firstiter)
        hooks = sys.get_asyncgen_hooks()
        self.assertIs(hooks.firstiter, firstiter)
        self.assertIs(hooks[0], firstiter)
        self.assertIs(hooks.finalizer, None)
        self.assertIs(hooks[1], None)

        finalizer = lambda *a: None
        sys.set_asyncgen_hooks(finalizer=finalizer)
        hooks = sys.get_asyncgen_hooks()
        self.assertIs(hooks.firstiter, firstiter)
        self.assertIs(hooks[0], firstiter)
        self.assertIs(hooks.finalizer, finalizer)
        self.assertIs(hooks[1], finalizer)

        sys.set_asyncgen_hooks(*old)
        cur = sys.get_asyncgen_hooks()
        self.assertIsNone(cur.firstiter)
        self.assertIsNone(cur.finalizer)
Exemplo n.º 2
0
    def test_asyncgen_hooks(self):
        import sys
        old = sys.get_asyncgen_hooks()
        assert old.firstiter is None
        assert old.finalizer is None

        firstiter = lambda *a: None
        sys.set_asyncgen_hooks(firstiter=firstiter)
        hooks = sys.get_asyncgen_hooks()
        assert hooks.firstiter is firstiter
        assert hooks[0] is firstiter
        assert hooks.finalizer is None
        assert hooks[1] is None

        finalizer = lambda *a: None
        sys.set_asyncgen_hooks(finalizer=finalizer)
        hooks = sys.get_asyncgen_hooks()
        assert hooks.firstiter is firstiter
        assert hooks[0] is firstiter
        assert hooks.finalizer is finalizer
        assert hooks[1] is finalizer

        sys.set_asyncgen_hooks(*old)
        cur = sys.get_asyncgen_hooks()
        assert cur.firstiter is None
        assert cur.finalizer is None
    def test_asyncgen_hooks(self):
        old = sys.get_asyncgen_hooks()
        self.assertIsNone(old.firstiter)
        self.assertIsNone(old.finalizer)

        firstiter = lambda *a: None
        sys.set_asyncgen_hooks(firstiter=firstiter)
        hooks = sys.get_asyncgen_hooks()
        self.assertIs(hooks.firstiter, firstiter)
        self.assertIs(hooks[0], firstiter)
        self.assertIs(hooks.finalizer, None)
        self.assertIs(hooks[1], None)

        finalizer = lambda *a: None
        sys.set_asyncgen_hooks(finalizer=finalizer)
        hooks = sys.get_asyncgen_hooks()
        self.assertIs(hooks.firstiter, firstiter)
        self.assertIs(hooks[0], firstiter)
        self.assertIs(hooks.finalizer, finalizer)
        self.assertIs(hooks[1], finalizer)

        sys.set_asyncgen_hooks(*old)
        cur = sys.get_asyncgen_hooks()
        self.assertIsNone(cur.firstiter)
        self.assertIsNone(cur.finalizer)
Exemplo n.º 4
0
def test_delegation_to_existing_hooks():
    record = []

    def my_firstiter(agen):
        record.append("firstiter " + agen.ag_frame.f_locals["arg"])

    def my_finalizer(agen):
        record.append("finalizer " + agen.ag_frame.f_locals["arg"])

    async def example(arg):
        try:
            yield 42
        finally:
            with pytest.raises(_core.Cancelled):
                await _core.checkpoint()
            record.append("trio collected " + arg)

    async def async_main():
        await step_outside_async_context(example("theirs"))
        assert 42 == await example("ours").asend(None)
        gc_collect_harder()
        assert record == ["firstiter theirs", "finalizer theirs"]
        record[:] = []
        await _core.wait_all_tasks_blocked()
        assert record == ["trio collected ours"]

    old_hooks = sys.get_asyncgen_hooks()
    sys.set_asyncgen_hooks(my_firstiter, my_finalizer)
    try:
        _core.run(async_main)
    finally:
        assert sys.get_asyncgen_hooks() == (my_firstiter, my_finalizer)
        sys.set_asyncgen_hooks(*old_hooks)
Exemplo n.º 5
0
    def _running_loop(self):
        # The setup and teardown code for run_forever
        # is split off into a contextmanager to be
        # able to reuse this code in GUI applications
        # (see the running_loop context manager
        # in ._helpers.
        old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(
            firstiter=self._asyncgen_firstiter_hook,
            finalizer=self._asyncgen_finalizer_hook,
        )
        self._running = True
        asyncio._set_running_loop(self)

        try:
            yield

        finally:
            self._running = False
            asyncio._set_running_loop(None)
            sys.set_asyncgen_hooks(*old_agen_hooks)

        if self._exception is not None:
            exc = self._exception
            self._exception = None
            raise exc
Exemplo n.º 6
0
    def run_forever(self):
        if sys.version_info >= (3, 7, 0):
            set_coro_tracking = self._set_coroutine_origin_tracking
        else:
            set_coro_tracking = self._set_coroutine_wrapper

        self._check_closed()
        old_thread_id = self._thread_id
        old_running_loop = events._get_running_loop()
        set_coro_tracking(self._debug)
        self._thread_id = threading.get_ident()

        if self._asyncgens is not None:
            old_agen_hooks = sys.get_asyncgen_hooks()
            sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                   finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            while True:
                self._run_once()
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = old_thread_id
            events._set_running_loop(old_running_loop)
            set_coro_tracking(False)
            if self._asyncgens is not None:
                sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 7
0
def test_asyncgen_hooks_shutdown():
    finalized = 0
    asyncgens = []

    def register_agen(agen):
        asyncgens.append(agen)

    async def waiter(timeout):
        nonlocal finalized
        try:
            await suspend('running waiter')
            yield 1
        finally:
            await suspend('closing waiter')
            finalized += 1

    async def wait():
        async for _ in waiter(1):
            pass

    task1 = wait()
    task2 = wait()
    old_hooks = sys.get_asyncgen_hooks()
    try:
        sys.set_asyncgen_hooks(firstiter=register_agen)
        assert task1.send(None) == 'running waiter'
        assert task2.send(None) == 'running waiter'
        assert len(asyncgens) == 2

        assert run_async(asyncgens[0].aclose()) == (['closing waiter'], None)
        assert run_async(asyncgens[1].aclose()) == (['closing waiter'], None)
        assert finalized == 2
    finally:
        sys.set_asyncgen_hooks(*old_hooks)
Exemplo n.º 8
0
def asyncgen_manager():
    if hasattr(sys, 'get_asyncgen_hooks'):
        old_asyncgen_hooks = sys.get_asyncgen_hooks()

        def _init_async_gen(agen):
            # It's possible that we've come here through @asynccontextmanager in the contextlib module.
            # If so, we assume that the generator is being managed properly and allow it through.
            f = sys._getframe(1)
            if f.f_code.co_name == '__aenter__' and 'contextlib' in f.f_code.co_filename:
                return

            # Inspect the code of the generator to see if it might be safe
            if not is_safe_generator(agen) and not finalize.is_finalized(agen):
                raise RuntimeError(
                    "Async generator with async finalization must be wrapped by\n"
                    "async with curio.meta.finalize(agen) as agen:\n"
                    "    async for n in agen:\n"
                    "         ...\n"
                    "See PEP 533 for further discussion.")

        sys.set_asyncgen_hooks(_init_async_gen)
    try:
        yield
    finally:
        if hasattr(sys, 'get_asyncgen_hooks'):
            sys.set_asyncgen_hooks(*old_asyncgen_hooks)
Exemplo n.º 9
0
    def run_forever(self):
        self._check_closed()
        old_thread_id = self._thread_id
        old_running_loop = events._get_running_loop()
        set_coro_tracking(self._debug)
        self._thread_id = threading.get_ident()

        old_agen_hooks = sys.get_asyncgen_hooks()
        if self._asyncgens is not None:
            sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                   finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            while True:
                try:
                    self._run_once()
                except IndexError:
                    # Ignore 'pop from an empty deque' errors.
                    # This happens when all ready handles have already been
                    # processed but _run_once expects there to be more.
                    # Since the handles have been processed anyway it is
                    # safe to ignore this.
                    pass
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = old_thread_id
            events._set_running_loop(old_running_loop)
            set_coro_tracking(False)
            if self._asyncgens is not None:
                sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 10
0
    def _do_it(self, start_fn, *args):
        if not self._hooks_inited:
            self._hooks_inited = True
            (firstiter, self._finalizer) = get_asyncgen_hooks()
            if firstiter is not None:
                firstiter(self)
            if sys.implementation.name == "pypy":
                self._pypy_issue2786_workaround.add(self._coroutine)

        # On CPython 3.5.2 (but not 3.5.0), coroutines get cranky if you try
        # to iterate them after they're exhausted. Generators OTOH just raise
        # StopIteration. We want to convert the one into the other, so we need
        # to avoid iterating stopped coroutines.
        if getcoroutinestate(self._coroutine) is CORO_CLOSED:
            raise StopAsyncIteration()

        async def step():
            if self.ag_running:
                raise ValueError("async generator already executing")
            try:
                self.ag_running = True
                return await ANextIter(self._it, start_fn, *args)
            except StopAsyncIteration:
                self._pypy_issue2786_workaround.discard(self._coroutine)
                raise
            finally:
                self.ag_running = False

        return step()
Exemplo n.º 11
0
 def asyncgen_hooks(self, firstiter, finalizer):
     old_agen_hooks = sys.get_asyncgen_hooks()
     sys.set_asyncgen_hooks(firstiter=firstiter, finalizer=finalizer)
     try:
         yield None
     finally:
         sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 12
0
    def run_forever(self, app_context):
        """Set up the asyncio event loop, integrate it with the Winforms
        event loop, and start the application.

        This largely duplicates the setup behavior of the default Proactor
        run_forever implementation.

        :param app_context: The WinForms.ApplicationContext instance
            controlling the lifecycle of the app.
        """
        # Remember the application context.
        self.app_context = app_context

        # Register a custom user window message.
        self.msg_id = user32.RegisterWindowMessageA("Python asyncio tick")
        # Add a message filter to listen for the asyncio tick message
        # FIXME: Actually install the message filter.
        # msg_filter = AsyncIOTickMessageFilter(self, self.msg_id)
        # WinForms.Application.AddMessageFilter(msg_filter)

        # Setup the Proactor.
        # The code between the following markers should be exactly the same as
        # the official CPython implementation, up to the start of the
        # `while True:` part of run_forever() (see BaseEventLoop.run_forever()
        # in Lib/ascynio/base_events.py)
        # === START BaseEventLoop.run_forever() setup ===
        self._check_closed()
        if self.is_running():
            raise RuntimeError('This event loop is already running')
        if events._get_running_loop() is not None:
            raise RuntimeError(
                'Cannot run the event loop while another loop is running')
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()
        try:
            self._old_agen_hooks = sys.get_asyncgen_hooks()
            sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                   finalizer=self._asyncgen_finalizer_hook)
        except AttributeError:
            # Python < 3.6 didn't have sys.get_asyncgen_hooks();
            # No action required for those versions.
            pass

        events._set_running_loop(self)
        # === END BaseEventLoop.run_forever() setup ===

        # Rather than going into a `while True:` loop, we're going to use the
        # Winforms event loop to queue a tick() message that will cause a
        # single iteration of the asyncio event loop to be executed. Each time
        # we do this, we queue *another* tick() message in 5ms time. In this
        # way, we'll get a continuous stream of tick() calls, without blocking
        # the Winforms event loop.

        # Queue the first asyncio tick.
        self.enqueue_tick()

        # Start the Winforms event loop.
        WinForms.Application.Run(self.app_context)
Exemplo n.º 13
0
    def start_slave_loop(self):
        self._check_closed()
        self._check_running()
        self._set_coroutine_origin_tracking(self._debug)

        self._old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                               finalizer=self._asyncgen_finalizer_hook)
        asyncio.events._set_running_loop(self)
Exemplo n.º 14
0
    def begin(self):
        # We are now in charge of finalizing asynchronous generators (see docs about
        # sys.get_asyncgen_hooks). Note: these are also called 'hooks', but of course this is
        # just a name clash. They are not the same sort of hook as the tf.estimator.SessionRunHook
        self._original_sys_asyncgen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._alive_asyncgens.add,
                               finalizer=self._finalize_asyncgen)

        super().begin()
        self._update_hook_list()
Exemplo n.º 15
0
 def _managing_async_generators(self):
     original_hooks = sys.get_asyncgen_hooks()
     sys.set_asyncgen_hooks(
         firstiter=self._async_generator_firstiter_hook,
         finalizer=self._async_generator_finalizer_hook,
     )
     try:
         yield
     finally:
         sys.set_asyncgen_hooks(*original_hooks)
Exemplo n.º 16
0
 def manage_asyncgens(self):
     old_agen_hooks = sys.get_asyncgen_hooks()
     try:
         self._set_coroutine_origin_tracking(self._debug)
         if self._asyncgens is not None:
             sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                    finalizer=self._asyncgen_finalizer_hook)
         yield
     finally:
         self._set_coroutine_origin_tracking(False)
         if self._asyncgens is not None:
             sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 17
0
 def manage_asyncgens(self):
     if not hasattr(sys, 'get_asyncgen_hooks'):
         # Python version is too old.
         return
     old_agen_hooks = sys.get_asyncgen_hooks()
     try:
         self._set_coroutine_origin_tracking(self._debug)
         if self._asyncgens is not None:
             sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                    finalizer=self._asyncgen_finalizer_hook)
         yield
     finally:
         self._set_coroutine_origin_tracking(False)
         if self._asyncgens is not None:
             sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 18
0
    def start_slave_loop(self):
        """
        Prepare loop to be run by the GLib main event loop.
        asyncio.get_event_loop() and asyncio.get_running_loop() will
        return self, but self.is_running() will return False.
        """
        self._check_closed()
        self._check_running()
        self._set_coroutine_origin_tracking(self._debug)

        self._old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                               finalizer=self._asyncgen_finalizer_hook)
        asyncio.events._set_running_loop(self)
        self._is_slave = True
Exemplo n.º 19
0
    def run_forever(self):
        self._check_closed()
        self._check_running()
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()

        old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                               finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            g_main_loop_run(self._main_loop)
        finally:
            self._thread_id = None
            events._set_running_loop(None)
            self._set_coroutine_origin_tracking(False)
            sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 20
0
def asyncgen_manager():
    if hasattr(sys, 'get_asyncgen_hooks'):
        old_asyncgen_hooks = sys.get_asyncgen_hooks()
        def _fini_async_gen(agen):
            if agen.ag_frame is not None:
                raise RuntimeError("Async generator with async finalization must be wrapped by\n"
                                   "async with curio.meta.finalize(agen) as agen:\n"
                                   "    async for n in agen:\n"
                                   "         ...\n"
                                   "See PEP 533 for further discussion.")

        sys.set_asyncgen_hooks(None, _fini_async_gen)
    try:
        yield
    finally:
        if hasattr(sys, 'get_asyncgen_hooks'):
            sys.set_asyncgen_hooks(*old_asyncgen_hooks)
Exemplo n.º 21
0
    def run_forever_cooperatively(self):
        """Configure the event loop so it is started, doing as little work as possible to
        ensure that. Most Android interop objects are created lazily so that the cost of
        event loop interop is not paid by apps that don't use the event loop."""
        # Based on `BaseEventLoop.run_forever()` in CPython.
        if self.is_running():
            raise RuntimeError(
                "Refusing to start since loop is already running.")
        if self._closed:
            raise RuntimeError("Event loop is closed. Create a new object.")
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()

        self._old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(
            firstiter=self._asyncgen_firstiter_hook,
            finalizer=self._asyncgen_finalizer_hook,
        )
        asyncio.events._set_running_loop(self)
Exemplo n.º 22
0
    def test_pickling3(self):
        old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=lambda agen: None,
                               finalizer=async_gen_finalize)
        try:
            ag = self.ag()
        finally:
            sys.set_asyncgen_hooks(*old_agen_hooks)

        c = ag.__anext__()
        self.assertRaises(StopIteration, c.send, None)
        c = ag.__anext__()
        self.assertRaises(StopAsyncIteration, c.send, None)
        p = self.dumps(ag)
        ag = self.loads(p)
        self.assertIsNone(ag.ag_frame)
        self.assertRaises(StopIteration, c.send, None)
        c = ag.__anext__()
        self.assertRaises(StopAsyncIteration, c.send, None)
Exemplo n.º 23
0
def asyncgen_manager():
    if hasattr(sys, 'get_asyncgen_hooks'):
        old_asyncgen_hooks = sys.get_asyncgen_hooks()

        def _init_async_gen(agen):
            if not is_safe_generator(agen) and not finalize.is_finalized(agen):
                # Inspect the code of the generator to see if it might be safe 
                raise RuntimeError("Async generator with async finalization must be wrapped by\n"
                                   "async with curio.meta.finalize(agen) as agen:\n"
                                   "    async for n in agen:\n"
                                   "         ...\n"
                                   "See PEP 533 for further discussion.")

        sys.set_asyncgen_hooks(_init_async_gen)
    try:
        yield
    finally:
        if hasattr(sys, 'get_asyncgen_hooks'):
            sys.set_asyncgen_hooks(*old_asyncgen_hooks)
Exemplo n.º 24
0
    def run_forever_cooperatively(self):
        # Based heavily on `BaseEventLoop.run_forever()`` in CPython.
        if self.is_running():
            raise RuntimeError(
                "Refusing to start since loop is already running.")
        if self._closed:
            raise RuntimeError("Event loop is closed. Create a new object.")
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()

        self._old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(
            firstiter=self._asyncgen_firstiter_hook,
            finalizer=self._asyncgen_finalizer_hook,
        )
        asyncio.events._set_running_loop(self)

        # Create Android handler to run our own code on. We assume that we are running
        # in the main Android activity thread, and we therefore do not worry about thread safety.
        Handler = JavaClass("android/os/Handler")
        self._handler = Handler(
        )  # No-arg constructor uses main Android event loop.
        # Create a Java Runnables to tick the event loop forward. We statically create
        # Runnables to avoid creating lots of temporary objects.
        python_self = self

        class RunScheduledCallbacksThenRestartLoopRunnable(Runnable):
            def run(self):
                python_self._run_scheduled_callbacks_then_restart_loop()

        class RunEventLoopOnceCooperativelyRunnable(Runnable):
            def run(self):
                python_self._run_event_loop_once_cooperatively()

        self._runnables = {
            "_run_scheduled_callbacks_then_restart_loop":
            RunScheduledCallbacksThenRestartLoopRunnable(),
            "_run_event_loop_once_cooperatively":
            RunEventLoopOnceCooperativelyRunnable(),
        }
        self._run_event_loop_once_cooperatively()
        print("Started event loop")
Exemplo n.º 25
0
def asyncgen_manager():
    if hasattr(sys, 'get_asyncgen_hooks'):
        old_asyncgen_hooks = sys.get_asyncgen_hooks()

        def _init_async_gen(agen):
            if not is_safe_generator(agen) and not finalize.is_finalized(agen):
                # Inspect the code of the generator to see if it might be safe
                raise RuntimeError(
                    "Async generator with async finalization must be wrapped by\n"
                    "async with curio.meta.finalize(agen) as agen:\n"
                    "    async for n in agen:\n"
                    "         ...\n"
                    "See PEP 533 for further discussion.")

        sys.set_asyncgen_hooks(_init_async_gen)
    try:
        yield
    finally:
        if hasattr(sys, 'get_asyncgen_hooks'):
            sys.set_asyncgen_hooks(*old_asyncgen_hooks)
Exemplo n.º 26
0
    def run_forever_37(self):
        # from Python 3.7 asyncio.base_events
        self._check_closed()
        old_thread_id = self._thread_id
        old_running_loop = events._get_running_loop()
        self._set_coroutine_origin_tracking(self._debug)
        self._thread_id = threading.get_ident()

        old_agen_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                               finalizer=self._asyncgen_finalizer_hook)
        try:
            events._set_running_loop(self)
            while True:
                self._run_once()
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = old_thread_id
            events._set_running_loop(old_running_loop)
            self._set_coroutine_origin_tracking(False)
            sys.set_asyncgen_hooks(*old_agen_hooks)
Exemplo n.º 27
0
def test_async_aclose_in_finalize_hook_await_in_finally():
    import gc
    state = 0
    async def ag():
        nonlocal state
        try:
            yield
        finally:
            state = 1
            await suspend('coro')
            state = 2

    async def run():
        a = ag()
        async for i in a:
            break
        del a
        gc.collect()
        gc.collect()
        gc.collect()
    a = run()

    a2 = None
    assert sys.get_asyncgen_hooks() == (None, None)
    def _finalize(g):
        nonlocal a2
        a2 = g.aclose()
    sys.set_asyncgen_hooks(finalizer=_finalize)
    assert state == 0
    with pytest.raises(StopIteration):
        a.send(None)
    assert a2.send(None) == 'coro'
    assert state == 1
    with pytest.raises(StopIteration):
        a2.send(None)
    assert state == 2
    sys.set_asyncgen_hooks(None, None)
Exemplo n.º 28
0
def safe_get_asyncgen_hooks():
    try:
        return sys.get_asyncgen_hooks()
    except Exception:
        return None
Exemplo n.º 29
0
    def install_hooks(self, runner):
        def firstiter(agen):
            if hasattr(_run.GLOBAL_RUN_CONTEXT, "task"):
                self.alive.add(agen)
            else:
                # An async generator first iterated outside of a Trio
                # task doesn't belong to Trio. Probably we're in guest
                # mode and the async generator belongs to our host.
                # The locals dictionary is the only good place to
                # remember this fact, at least until
                # https://bugs.python.org/issue40916 is implemented.
                agen.ag_frame.f_locals["@trio_foreign_asyncgen"] = True
                if self.prev_hooks.firstiter is not None:
                    self.prev_hooks.firstiter(agen)

        def finalize_in_trio_context(agen, agen_name):
            try:
                runner.spawn_system_task(
                    self._finalize_one,
                    agen,
                    agen_name,
                    name=f"close asyncgen {agen_name} (abandoned)",
                )
            except RuntimeError:
                # There is a one-tick window where the system nursery
                # is closed but the init task hasn't yet made
                # self.asyncgens a strong set to disable GC. We seem to
                # have hit it.
                self.trailing_needs_finalize.add(agen)

        def finalizer(agen):
            agen_name = name_asyncgen(agen)
            try:
                is_ours = not agen.ag_frame.f_locals.get(
                    "@trio_foreign_asyncgen")
            except AttributeError:  # pragma: no cover
                is_ours = True

            if is_ours:
                runner.entry_queue.run_sync_soon(finalize_in_trio_context,
                                                 agen, agen_name)

                # Do this last, because it might raise an exception
                # depending on the user's warnings filter. (That
                # exception will be printed to the terminal and
                # ignored, since we're running in GC context.)
                warnings.warn(
                    f"Async generator {agen_name!r} was garbage collected before it "
                    f"had been exhausted. Surround its use in 'async with "
                    f"aclosing(...):' to ensure that it gets cleaned up as soon as "
                    f"you're done using it.",
                    ResourceWarning,
                    stacklevel=2,
                    source=agen,
                )
            else:
                # Not ours -> forward to the host loop's async generator finalizer
                if self.prev_hooks.finalizer is not None:
                    self.prev_hooks.finalizer(agen)
                else:
                    # Host has no finalizer.  Reimplement the default
                    # Python behavior with no hooks installed: throw in
                    # GeneratorExit, step once, raise RuntimeError if
                    # it doesn't exit.
                    closer = agen.aclose()
                    try:
                        # If the next thing is a yield, this will raise RuntimeError
                        # which we allow to propagate
                        closer.send(None)
                    except StopIteration:
                        pass
                    else:
                        # If the next thing is an await, we get here. Give a nicer
                        # error than the default "async generator ignored GeneratorExit"
                        raise RuntimeError(
                            f"Non-Trio async generator {agen_name!r} awaited something "
                            f"during finalization; install a finalization hook to "
                            f"support this, or wrap it in 'async with aclosing(...):'"
                        )

        self.prev_hooks = sys.get_asyncgen_hooks()
        sys.set_asyncgen_hooks(firstiter=firstiter, finalizer=finalizer)
Exemplo n.º 30
0
    def __init__(self, hooks=None):
        super().__init__(hooks)

        self._original_sys_asyncgen_hooks = sys.get_asyncgen_hooks()
        self._alive_asyncgens = weakref.WeakSet()
        self._new_hooks = collections.deque()
Exemplo n.º 31
0
    def run(self, coro=None, *, shutdown=False, timeout=None):
        if coro and self._crashed:
            raise RuntimeError(
                "Can't submit further tasks to a crashed kernel.")

        if getattr(self._local, 'running', False):
            raise RuntimeError('Only one Curio kernel per thread is allowed')
        self._local.running = True

        if hasattr(sys, 'get_asyncgen_hooks'):
            asyncgen_hooks = sys.get_asyncgen_hooks()
        try:
            if not self._runner:
                self._runner = self._run_coro()
                self._runner.send(None)

            # Submit the given coroutine (if any)
            try:
                if coro or not shutdown:
                    ret_val, ret_exc = self._runner.send((coro, timeout))
                else:
                    ret_val = ret_exc = None
            except BaseException as e:
                # If the underlying runner coroutine died for some reason,
                # then something bad happened.  Maybe a KeyboardInterrupt
                # an internal programming program.  We'll remove it and
                # mark the kernel as crashed.   It's still possible that someone
                # will attempt a kernel shutdown later.
                self._runner = None
                self._crashed = True
                raise

            # If shutdown has been requested, run the shutdown process
            if shutdown:
                # For "reasons" related to task scheduling, the task
                # of shutting down all remaining tasks is best managed
                # by a launching a task dedicated to carrying out the task (sic)
                async def _shutdown_tasks(tocancel):
                    for task in tocancel:
                        try:
                            await task.cancel()
                        except Exception as e:
                            log.error(
                                'Exception %r ignored in curio shutdown' % e,
                                exc_info=True)

                while self._tasks:
                    tocancel = [
                        task for task in self._tasks.values()
                        if task.id != self._kernel_task_id
                    ]
                    tocancel.sort(key=lambda t: t.id)
                    if self._kernel_task_id:
                        tocancel.append(self._tasks[self._kernel_task_id])
                    for task in tocancel:
                        task.daemon = True
                    self._runner.send((_shutdown_tasks(tocancel), None))
                    self._kernel_task_id = None
                self._runner.close()
                del self._runner
                self._shutdown_resources()

            if ret_exc:
                raise ret_exc
            else:
                return ret_val

        finally:
            self._local.running = False
            if hasattr(sys, 'set_asyncgen_hooks'):
                sys.set_asyncgen_hooks(*asyncgen_hooks)
Exemplo n.º 32
0
# sys.settrace(test)
print("xxxxxxxxxxxxxxxx", sys.gettrace())

print(sys.getwindowsversion())


def firstiter():
    print('from firstiter.')


def finalizer():
    print('from finalizer.')


sys.set_asyncgen_hooks(firstiter, finalizer)
print(sys.get_asyncgen_hooks())

print(sys.get_coroutine_origin_tracking_depth())

print(sys.hash_info)

print(sys.hexversion)
print(sys.implementation)

print(sys.int_info)

print(sys.__interactivehook__)

s1 = sys.intern('hello!哈哈')
s2 = 'hello!哈哈'
s3 = ('hello!哈哈')