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
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))
def test_not_cython_func(func): assert is_python_func(func)
def test_is_cython_func(func): assert not is_python_func(func)