Suggestion: Paginated Field
I'm not sure if this will be useful to the library, but I've created a paginated_field decorator for my project to make it easier to create fields which support pagination in a consistent yet DRY manner. Essentially, the decorator wraps an Object inside a dynamically-generated Object class; the original Object becomes the data field and a page_info field is added.
Before:
{"myQuery": {"someField": "Foo", "someOtherField": "Bar"}}
After:
{"myQuery": {"data": {"someField": "Foo", "someOtherField": "Bar"}, "pageInfo": {"cursor": "some-cursor"}}}
Usage:
@paginated_field(MyObjectSchema)
def pwnd_emails(self, count: int = 10, cursor: str = None) -> Tuple[List[MyObjectSchema], str]:
user_id = context.get().variables['user_id']
data, cursor = get_my_objects(
user_id, as_dicts=True,
limit=count, cursor=cursor
)
return [MyObjectSchema(**d) for d in data], cursor
Note that the method's return annotation is Tuple[List[MyObjectSchema], str]: this allows IDEs to correctly type hint and accept the method's return type. The paginated_field decorator (see below) changes the field's return type to reflect the correct GraphQL schema when the schema is generated.
So far, this is working well for me (although it is currently un-tested). If @ethe thinks it would be a useful addition to the library, I can update the code below to be more generic and to add support for more fields on PageInfo.
class PageInfo(Object):
cursor: Optional[str]
class PaginatedObject(Object):
page_info: PageInfo
PAGINATED_CLASSES = {}
def paginated_field(schema_type):
new_name = f'Paginated{schema_type.__name__}'
new_class = PAGINATED_CLASSES.get(new_name)
if not new_class:
new_class = make_dataclass(
new_name,
fields=[('data', List[schema_type])],
bases=(PaginatedObject, )
)
PAGINATED_CLASSES[new_name] = new_class
def decorator(f):
f.__is_field__ = True
f.__annotations__['return'] = PaginatedObject
@wraps(f)
def wrapper(*args, **kwargs):
data, cursor = f(*args, **kwargs)
# noinspection PyArgumentList
return new_class(data=data, page_info=PageInfo(cursor=cursor))
return wrapper
return decorator
Suggestions welcome!
GraphQL provides pagination support in Relay but does not give an independent component. Pygraphy may take a long time to support Relay, and I also do not want to extend GraphQL. So it is sorry for supporting the pagination query now, you can still make some custom tools to support it.