Ejemplo n.º 1
0
    def call_at(cls, when, callback, *args, **kwargs):
        """指定时间调用(能隔离上下文)
        """

        loop = asyncio.events.get_event_loop()

        if kwargs:

            return loop.call_at(
                when,
                async_adapter(
                    cls.func_partial(
                        callback,
                        *args,
                        **kwargs
                    )
                ),
                context=Context()
            )

        else:

            return loop.call_at(
                when,
                async_adapter(callback),
                *args,
                context=Context()
            )
Ejemplo n.º 2
0
def _exec_listener_thread_safe(loop: AbstractEventLoop,
                               listener: ListenerCb[K], context: Context,
                               event_instance: K) -> "Future[None]":
    # Create an internal future to better control the listener result
    result_future: "Future[None]" = loop.create_future()
    listener_loop = retrieve_loop_from_listener(listener) or loop
    if loop is listener_loop:
        context.run(
            _exec_listener,
            loop,
            result_future.cancel,
            result_future.set_exception,
            result_future.set_result,
            listener,
            event_instance,
        )
    else:
        listener_loop.call_soon_threadsafe(
            context.run,
            _exec_listener,
            listener_loop,
            partial(loop.call_soon_threadsafe, result_future.cancel),
            partial(loop.call_soon_threadsafe, result_future.set_exception),
            partial(loop.call_soon_threadsafe, result_future.set_result),
            listener,
            event_instance,
        )

    return result_future
Ejemplo n.º 3
0
    def call_soon_threadsafe(cls, callback, *args, **kwargs):
        """延时调用(线程安全,能隔离上下文)
        """

        loop = asyncio.events.get_event_loop()

        if kwargs:

            return loop.call_soon_threadsafe(
                async_adapter(
                    cls.func_partial(
                        callback,
                        *args,
                        **kwargs
                    )
                ),
                context=Context()
            )

        else:

            return loop.call_soon_threadsafe(
                async_adapter(callback),
                *args,
                context=Context()
            )
Ejemplo n.º 4
0
    def call_later(cls, delay, callback, *args, **kwargs):
        """延时指定秒数调用(能隔离上下文)
        """

        loop = asyncio.events.get_event_loop()

        if kwargs:

            return loop.call_later(
                delay,
                async_adapter(
                    cls.func_partial(
                        callback,
                        *args,
                        **kwargs
                    )
                ),
                context=Context()
            )

        else:

            return loop.call_later(
                delay,
                async_adapter(callback),
                *args,
                context=Context()
            )
Ejemplo n.º 5
0
    def call_soon(cls, callback, *args, **kwargs):

        loop = asyncio.events.get_event_loop()

        if kwargs:

            return loop.call_soon(async_adapter(
                cls.func_partial(callback, *args, **kwargs)),
                                  context=Context())

        else:

            return loop.call_soon(async_adapter(callback),
                                  *args,
                                  context=Context())
Ejemplo n.º 6
0
 def _get_context():
     state = _get_state()
     ctx = getattr(state, 'context', None)
     if ctx is None:
         ctx = Context()
         state.context = ctx
     return ctx
Ejemplo n.º 7
0
def context(event_loop, request):
    """Create an empty context for the async test case and it's async fixtures."""
    context = Context()
    def taskfactory(loop, coro):
        return Task(coro, loop=loop, context=context)
    event_loop.set_task_factory(taskfactory)
    return context
Ejemplo n.º 8
0
    def test_context_assignment_different_thread(self):
        import threading

        ctx = Context()
        var = ContextVar("var", default=None)
        is_running = threading.Event()
        should_suspend = threading.Event()
        did_suspend = threading.Event()
        should_exit = threading.Event()
        holder = []

        def greenlet_in_thread_fn():
            var.set(1)
            is_running.set()
            should_suspend.wait()
            var.set(2)
            getcurrent().parent.switch()
            holder.append(var.get())

        def thread_fn():
            gr = greenlet(greenlet_in_thread_fn)
            gr.gr_context = ctx
            holder.append(gr)
            gr.switch()
            did_suspend.set()
            should_exit.wait()
            gr.switch()

        thread = threading.Thread(target=thread_fn, daemon=True)
        thread.start()
        is_running.wait()
        gr = holder[0]

        # Can't access or modify context if the greenlet is running
        # in a different thread
        with self.assertRaisesRegex(ValueError, "running in a different"):
            getattr(gr, 'gr_context')
        with self.assertRaisesRegex(ValueError, "running in a different"):
            gr.gr_context = None

        should_suspend.set()
        did_suspend.wait()

        # OK to access and modify context if greenlet is suspended
        self.assertIs(gr.gr_context, ctx)
        self.assertEqual(gr.gr_context[var], 2)
        gr.gr_context = None

        should_exit.set()
        thread.join()

        self.assertEqual(holder, [gr, None])

        # Context can still be accessed/modified when greenlet is dead:
        self.assertIsNone(gr.gr_context)
        gr.gr_context = ctx
        self.assertIs(gr.gr_context, ctx)
Ejemplo n.º 9
0
 def _run_in_thread(self, future: Awaitable[RetT], ctx: Context) -> RetT:
     loop = self._local.event_loop
     ret = ctx.run(loop.run_until_complete, future)
     return cast(RetT, ret)
Ejemplo n.º 10
0
def format_image_url_filter(ctx: Context, value: str) -> str:
    return ctx.get("root_url", "") + "/images" + value
Ejemplo n.º 11
0
def format_url_filter(ctx: Context, value: str) -> str:
    return (
        ctx.get("root_url", "")
        + value
        + ("/index.html" if ctx.get("is_export") else "")
    )
Ejemplo n.º 12
0
 def _run_in_thread(self, future: Awaitable[RetT], ctx: Context) -> RetT:
     loop = self._local.event_loop
     ret = ctx.run(loop.run_until_complete, future)
     return cast(RetT, ret)
Ejemplo n.º 13
0
    def test_context_assignment_different_thread(self):
        import threading
        VAR_VAR.set(None)
        ctx = Context()

        is_running = threading.Event()
        should_suspend = threading.Event()
        did_suspend = threading.Event()
        should_exit = threading.Event()
        holder = []

        def greenlet_in_thread_fn():
            VAR_VAR.set(1)
            is_running.set()
            should_suspend.wait(10)
            VAR_VAR.set(2)
            getcurrent().parent.switch()
            holder.append(VAR_VAR.get())

        def thread_fn():
            gr = greenlet(greenlet_in_thread_fn)
            gr.gr_context = ctx
            holder.append(gr)
            gr.switch()
            did_suspend.set()
            should_exit.wait(10)
            gr.switch()
            del gr
            greenlet()  # trigger cleanup

        thread = threading.Thread(target=thread_fn, daemon=True)
        thread.start()
        is_running.wait(10)
        gr = holder[0]

        # Can't access or modify context if the greenlet is running
        # in a different thread
        with self.assertRaisesRegex(ValueError, "running in a different"):
            getattr(gr, 'gr_context')
        with self.assertRaisesRegex(ValueError, "running in a different"):
            gr.gr_context = None

        should_suspend.set()
        did_suspend.wait(10)

        # OK to access and modify context if greenlet is suspended
        self.assertIs(gr.gr_context, ctx)
        self.assertEqual(gr.gr_context[VAR_VAR], 2)
        gr.gr_context = None

        should_exit.set()
        thread.join(10)

        self.assertEqual(holder, [gr, None])

        # Context can still be accessed/modified when greenlet is dead:
        self.assertIsNone(gr.gr_context)
        gr.gr_context = ctx
        self.assertIs(gr.gr_context, ctx)

        # Otherwise we leak greenlets on some platforms.
        # XXX: Should be able to do this automatically
        del holder[:]
        gr = None
        thread = None