Ejemplo n.º 1
0
 def __repr__(self):
     typenames = ', '.join(qualified_name(cls) for cls in self.types)
     value_repr = ('factory=%s' % callable_name(self.value_or_factory) if self.is_factory
                   else 'value=%r' % self.value_or_factory)
     return ('{self.__class__.__name__}({value_repr}, types=[{typenames}], name={self.name!r}, '
             'context_attr={self.context_attr!r})'.format(
                 self=self, value_repr=value_repr, typenames=typenames))
Ejemplo n.º 2
0
    async def wrapper(*args, **kwargs) -> None:
        async def teardown_callback(exception: Optional[Exception]):
            try:
                await generator.asend(exception)
            except StopAsyncIteration:
                pass
            finally:
                await generator.aclose()

        try:
            ctx = next(arg for arg in args[:2] if isinstance(arg, Context))
        except StopIteration:
            raise RuntimeError('the first positional argument to {}() has to be a Context '
                               'instance'.format(callable_name(func))) from None

        generator = func(*args, **kwargs)
        try:
            await generator.asend(None)
        except StopAsyncIteration:
            pass
        except BaseException:
            await generator.aclose()
            raise
        else:
            ctx.add_teardown_callback(teardown_callback, True)
Ejemplo n.º 3
0
def context_teardown(func: Callable):
    """
    Wrap an async generator function to execute the rest of the function at context teardown.

    This function returns an async function, which, when called, starts the wrapped async
    generator. The wrapped async function is run until the first ``yield`` statement
    (``await async_generator.yield_()`` on Python 3.5). When the context is being torn down, the
    exception that ended the context, if any, is sent to the generator.

    For example::

        class SomeComponent(Component):
            @context_teardown
            async def start(self, ctx: Context):
                service = SomeService()
                ctx.add_resource(service)
                exception = yield
                service.stop()

    :param func: an async generator function
    :return: an async function

    """
    @wraps(func)
    async def wrapper(*args, **kwargs) -> None:
        async def teardown_callback(exception: Optional[Exception]):
            try:
                await generator.asend(exception)
            except StopAsyncIteration:
                pass
            finally:
                await generator.aclose()

        try:
            ctx = next(arg for arg in args[:2] if isinstance(arg, Context))
        except StopIteration:
            raise RuntimeError(
                'the first positional argument to {}() has to be a Context '
                'instance'.format(callable_name(func))) from None

        generator = func(*args, **kwargs)
        try:
            await generator.asend(None)
        except StopAsyncIteration:
            raise RuntimeError('{} did not do "await yield_()"'.format(
                callable_name(func))) from None
        except BaseException:
            await generator.aclose()
            raise
        else:
            ctx.add_teardown_callback(teardown_callback, True)

    if iscoroutinefunction(func):
        func = async_generator(func)
    elif not isasyncgenfunction(func):
        raise TypeError('{} must be an async generator function'.format(
            callable_name(func)))

    return wrapper
Ejemplo n.º 4
0
 def __repr__(self):
     typenames = ', '.join(qualified_name(cls) for cls in self.types)
     value_repr = ('factory=%s' % callable_name(self.value_or_factory) if
                   self.is_factory else 'value=%r' % self.value_or_factory)
     return (
         '{self.__class__.__name__}({value_repr}, types=[{typenames}], name={self.name!r}, '
         'context_attr={self.context_attr!r})'.format(self=self,
                                                      value_repr=value_repr,
                                                      typenames=typenames))
Ejemplo n.º 5
0
        def inner_wrapper(*args, **kwargs):
            try:
                ctx = next(arg for arg in args[:2] if isinstance(arg, Context))
            except StopIteration:
                raise RuntimeError('the first positional argument to {}() has to be a Context '
                                   'instance'.format(callable_name(func))) from None

            executor = ctx.require_resource(Executor, resource_name)
            return asyncio_extras.call_in_executor(func, *args, executor=executor, **kwargs)
Ejemplo n.º 6
0
def context_teardown(func: Callable):
    """
    Wrap an async generator function to execute the rest of the function at context teardown.

    This function returns an async function, which, when called, starts the wrapped async
    generator. The wrapped async function is run until the first ``yield`` statement
    (``await async_generator.yield_()`` on Python 3.5). When the context is being torn down, the
    exception that ended the context, if any, is sent to the generator.

    For example::

        class SomeComponent(Component):
            @context_teardown
            async def start(self, ctx: Context):
                service = SomeService()
                ctx.add_resource(service)
                exception = yield
                service.stop()

    :param func: an async generator function
    :return: an async function

    """
    @wraps(func)
    async def wrapper(*args, **kwargs) -> None:
        async def teardown_callback(exception: Optional[Exception]):
            try:
                await generator.asend(exception)
            except StopAsyncIteration:
                pass
            finally:
                await generator.aclose()

        try:
            ctx = next(arg for arg in args[:2] if isinstance(arg, Context))
        except StopIteration:
            raise RuntimeError('the first positional argument to {}() has to be a Context '
                               'instance'.format(callable_name(func))) from None

        generator = func(*args, **kwargs)
        try:
            await generator.asend(None)
        except StopAsyncIteration:
            pass
        except BaseException:
            await generator.aclose()
            raise
        else:
            ctx.add_teardown_callback(teardown_callback, True)

    if iscoroutinefunction(func):
        func = async_generator(func)
    elif not isasyncgenfunction(func):
        raise TypeError('{} must be an async generator function'.format(callable_name(func)))

    return wrapper
Ejemplo n.º 7
0
        def inner_wrapper(*args, **kwargs):
            try:
                ctx = next(arg for arg in args[:2] if isinstance(arg, Context))
            except StopIteration:
                raise RuntimeError(
                    'the first positional argument to {}() has to be a Context '
                    'instance'.format(callable_name(func))) from None

            executor = ctx.require_resource(Executor, resource_name)
            return asyncio_extras.call_in_executor(func,
                                                   *args,
                                                   executor=executor,
                                                   **kwargs)
Ejemplo n.º 8
0
def test_callable_name(inputval, expected):
    assert callable_name(inputval) == expected
Ejemplo n.º 9
0
def test_callable_name(inputval, expected):
    assert callable_name(inputval) == expected