def page_number(func): """ Decorator for adding pagination behavior to a view. That decorator produces a view based on page numbering and it adds three query parameters to control the pagination: page, page_size and count. Page has a default value of first page, page_size default value is defined in :class:`PageNumberResponse` and count defines if the response will define the total number of elements. The output schema is also modified by :class:`PageNumberSchema`, creating a new schema based on it but using the old output schema as the content of its data field. :param func: View to be decorated. :return: Decorated view. """ assert forge is not None, "`python-forge` must be installed to use Paginator." resource_schema = get_output_schema(func) data_schema = marshmallow.fields.Nested(resource_schema, many=True) if resource_schema else marshmallow.fields.Raw() schema = type( "PageNumberPaginated" + resource_schema.__class__.__name__, # Add a prefix to avoid collision (PageNumberSchema,), {"data": data_schema}, # Replace generic with resource schema )() forge_revision_list = ( forge.copy(func), forge.insert(forge.arg("page", default=None, type=int), index=-1), forge.insert(forge.arg("page_size", default=None, type=int), index=-1), forge.insert(forge.arg("count", default=True, type=bool), index=-1), forge.delete("kwargs"), forge.returns(schema), ) try: if asyncio.iscoroutinefunction(func): @forge.compose(*forge_revision_list) @functools.wraps(func) async def decorator(*args, page: int = None, page_size: int = None, count: bool = True, **kwargs): return PageNumberResponse( schema=schema, page=page, page_size=page_size, count=count, content=await func(*args, **kwargs) ) else: @forge.compose(*forge_revision_list) @functools.wraps(func) def decorator(*args, page: int = None, page_size: int = None, count: bool = True, **kwargs): return PageNumberResponse( schema=schema, page=page, page_size=page_size, count=count, content=func(*args, **kwargs) ) except ValueError as e: raise TypeError("Paginated views must define **kwargs param") from e return decorator
def forge_client_session(init): """ Forge CachedSession.__init__ method signature """ forged_signature = forge.compose( forge.copy(CachedSession.__init__), forge.insert( [ forge.kwarg("retry", default=True, type=bool), forge.kwarg("n_retries", default=3, type=int), ], before=lambda x: x.kind == Parameter.KEYWORD_ONLY, ), )(init) return forged_signature
import forge import aiohttp from typing import Dict, List, Union # RestClient signature decorators GET_SIGNATURE = forge.compose( forge.copy(aiohttp.ClientSession.get), forge.modify("url", default=None), forge.returns(aiohttp.ClientResponse), forge.insert( [ forge.kwo("parameters", default={}, type=Dict[str, Union[str, List[str]]]), forge.kwo("headers", default={}, type=Dict[str, str]), ], before=lambda arg: arg.kind == forge.FParameter.VAR_KEYWORD, ), ) MGET_SIGNATURE = forge.compose( forge.copy(aiohttp.ClientSession.get, exclude="url"), forge.returns(List[aiohttp.ClientResponse]), forge.insert( forge.pok( "urls", type=forge.fsignature(aiohttp.ClientSession.get)["url"].type, default=None, ), index=1,