示例#1
0
def prepare_middleware_ws(middleware):
    """Check middleware interfaces and prepare WebSocket methods for request handling.

    Note:
        This method is only applicable to ASGI apps.

    Arguments:
        middleware (iterable): An iterable of middleware objects.

    Returns:
        tuple: A two-item ``(request_mw, resource_mw)`` tuple, where
        *request_mw* is an ordered list of ``process_request_ws()`` methods,
        and *resource_mw* is an ordered list of ``process_resource_ws()``
        methods.
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []

    for component in middleware:
        process_request_ws = util.get_bound_method(component,
                                                   'process_request_ws')
        process_resource_ws = util.get_bound_method(component,
                                                    'process_resource_ws')

        for m in (process_request_ws, process_resource_ws):
            if not m:
                continue

            # NOTE(kgriffs): iscoroutinefunction() always returns False
            #   for cythonized functions.
            #
            #   https://github.com/cython/cython/issues/2273
            #   https://bugs.python.org/issue38225
            #
            if not iscoroutinefunction(m) and util.is_python_func(m):
                msg = '{} must be implemented as an awaitable coroutine.'
                raise CompatibilityError(msg.format(m))

        if process_request_ws:
            request_mw.append(process_request_ws)

        if process_resource_ws:
            resource_mw.append(process_resource_ws)

    return request_mw, resource_mw
示例#2
0
def prepare_middleware(middleware, independent_middleware=False, asgi=False):
    """Check middleware interfaces and prepare the methods for request handling.

    Arguments:
        middleware (iterable): An iterable of middleware objects.

    Keyword Args:
        independent_middleware (bool): ``True`` if the request and
            response middleware methods should be treated independently
            (default ``False``)
        asgi (bool): ``True`` if an ASGI app, ``False`` otherwise
            (default ``False``)

    Returns:
        tuple: A tuple of prepared middleware method tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []
    response_mw = []

    for component in middleware:
        # NOTE(kgriffs): Middleware that supports both WSGI and ASGI can
        #   append an *_async postfix to the ASGI version of the method
        #   to distinguish the two. Otherwise, the prefix is unnecessary.

        if asgi:
            process_request = (
                util.get_bound_method(component, 'process_request_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_request')))

            process_resource = (
                util.get_bound_method(component, 'process_resource_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_resource')))

            process_response = (
                util.get_bound_method(component, 'process_response_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_response')))

            for m in (process_request, process_resource, process_response):
                # NOTE(kgriffs): iscoroutinefunction() always returns False
                #   for cythonized functions.
                #
                #   https://github.com/cython/cython/issues/2273
                #   https://bugs.python.org/issue38225
                #
                if m and not iscoroutinefunction(m) and util.is_python_func(m):
                    msg = (
                        '{} must be implemented as an awaitable coroutine. If '
                        'you would like to retain compatibility '
                        'with WSGI apps, the coroutine versions of the '
                        'middleware methods may be implemented side-by-side '
                        'by applying an *_async postfix to the method names. ')
                    raise CompatibilityError(msg.format(m))

        else:
            process_request = util.get_bound_method(component,
                                                    'process_request')
            process_resource = util.get_bound_method(component,
                                                     'process_resource')
            process_response = util.get_bound_method(component,
                                                     'process_response')

            for m in (process_request, process_resource, process_response):
                if m and iscoroutinefunction(m):
                    msg = ('{} may not implement coroutine methods and '
                           'remain compatible with WSGI apps without '
                           'using the *_async postfix to explicitly identify '
                           'the coroutine version of a given middleware '
                           'method.')
                    raise CompatibilityError(msg.format(component))

        if not (process_request or process_resource or process_response):
            if asgi and (hasattr(component, 'process_startup')
                         or hasattr(component, 'process_shutdown')):
                # NOTE(kgriffs): This middleware only has ASGI lifespan
                #   event handlers
                continue

            msg = '{0} must implement at least one middleware method'
            raise TypeError(msg.format(component))

        # NOTE: depending on whether we want to execute middleware
        # independently, we group response and request middleware either
        # together or separately.
        if independent_middleware:
            if process_request:
                request_mw.append(process_request)
            if process_response:
                response_mw.insert(0, process_response)
        else:
            if process_request or process_response:
                request_mw.append((process_request, process_response))

        if process_resource:
            resource_mw.append(process_resource)

    return (tuple(request_mw), tuple(resource_mw), tuple(response_mw))
示例#3
0
def test_not_cython_func(func):
    assert is_python_func(func)
示例#4
0
def test_is_cython_func(func):
    assert not is_python_func(func)