Support optional GraphQL arguments for QueryValidator
playpauseandstop opened this issue · 3 comments
Long story short: GraphQL arguments can be optional without default value.
From GraphQL documentation,
Arguments can be either required or optional. When an argument is optional, we can define a default value - if the unit argument is not passed, it will be set to METER by default.
From GraphQL specification,
Arguments can be required. If the argument type is non‐null the argument is required and furthermore the explicit value null may not be provided. Otherwise, the argument is optional.
But in Hiku there is no way to provide optional arguments, when using QueryValidator
cause of,
def visit_option(self, obj):
default = _undefined if obj.default is None else obj.default
value = self._options.get(obj.name, default)
if value is _undefined:
node, field = self.for_
self.errors.report('Required option "{}.{}:{}" is not specified'
.format(node, field, obj.name))
Hiku enforces all options to be required or use non-null default values, which not conforms GraphQL specification cited above. As result right now there is impossible to mix QueryValidator
and optional arguments.
Code to reproduce,
Field(
'count_documents',
Integer,
resolve_count_documents,
options=[
Option('search', String, default=None),
Option('folder_id', Integer, default=None),
Option('status_id', Integer, default=None),
Option('signatures_to_finish', Integer, default=None),
Option('gte', String, default=None),
Option('lte', String, default=None),
]),
Works as expected for { count_documents }
query without QueryValidator
, but returns,
{
'data': None,
'errors': [
{'message': 'Required option "root.count_documents:search" is not specified'},
{'message': 'Required option "root.count_documents:folder_id" is not specified'},
{'message': 'Required option "root.count_documents:status_id" is not specified'},
{'message': 'Required option "root.count_documents:signatures_to_finish" is not specified'},
{'message': 'Required option "root.count_documents:gte" is not specified'},
{'message': 'Required option "root.count_documents:lte" is not specified'}
]
}
when Hiku handler contains,
validator = QueryValidator(graph)
validator.visit(query)
if validator.errors.list:
return web.json_response({'data': None, 'errors': ...})
Right now it is possible to handle this case by providing non-null, but some empty values for arguments of count_documents
field (like ''
) or by omitting QueryValidator
at all, but I'd prefer if Hiku works with GraphQL arguments due to specification and does not enforce all arguments to be required.
Agreed, the problem is that Hiku uses None as an indicator of that there are no default value. Should be trivial to fix, I will look into this as soon as I can.
Fixed in 7118e40, made a release candidate hiku==0.3.9rc1
for you for further testing, here is how to specify properly non-required options for GraphQL:
Option('search', Optional[String], default=None)
And there is an interesting case with default values:
Option('foo', Integer, default=123)
This option is totally valid in Hiku: it is not required, and if it will be missing in query, Hiku will use default value 123
and won't accept null
values. But in GraphQL this option will be required. As your quote from specification says:
If the argument type is non‐null the argument is required
So GraphQL here is slightly less flexible and Hiku maybe is slightly more complicated, as it gives you ability to distinguish when value is null
and when it is missing.
Updated Hiku to 0.3.9rc1
and can confirm that optional arguments work as expected with query validation.
Thanks!