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!
I'm not sure if this will be useful to the library, but I've created a
paginated_fielddecorator for my project to make it easier to create fields which support pagination in a consistent yet DRY manner. Essentially, the decorator wraps anObjectinside a dynamically-generatedObjectclass; the originalObjectbecomes thedatafield and apage_infofield is added.Before:
After:
Usage:
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. Thepaginated_fielddecorator (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.Suggestions welcome!