ivelum / graphql-py Goto Github PK
View Code? Open in Web Editor NEWPython GraphQL parser
License: MIT License
Python GraphQL parser
License: MIT License
I've been experimenting with this package by following along with the graphql.org docs. First I would like to say great work.
I tested the following example and got back a SyntaxError
.
In [39]: query = """
....: {
....: hero {
....: name
....: ...DroidFields
....: }
....: }
....:
....: fragment DroidFields on Droid {
....: primaryFunction
....: }
....: """
In [40]: doc = parser.parse(query)
---------------------------------------------------------------------------
SyntaxError Traceback (most recent call last)
<ipython-input-40-0c230401c2eb> in <module>()
----> 1 doc = parser.parse(query)
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/graphql/parser.pyc in parse(self, input, lexer, **kwargs)
34 def parse(self, input=None, lexer=None, **kwargs):
35 lexer = lexer or self.default_lexer
---> 36 return self.yacc.parse(input=input, lexer=lexer, **kwargs)
37
38 start = 'document'
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/ply/yacc.pyc in parse(self, input, lexer, debug, tracking, tokenfunc)
329 return self.parseopt(input, lexer, debug, tracking, tokenfunc)
330 else:
--> 331 return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
332
333
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/ply/yacc.pyc in parseopt_notrack(self, input, lexer, debug, tracking, tokenfunc)
1179 if errtoken and not hasattr(errtoken, 'lexer'):
1180 errtoken.lexer = lexer
-> 1181 tok = call_errorfunc(self.errorfunc, errtoken, self)
1182 if self.errorok:
1183 # User must have done some kind of panic
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/ply/yacc.pyc in call_errorfunc(errorfunc, token, parser)
191 _token = parser.token
192 _restart = parser.restart
--> 193 r = errorfunc(token)
194 try:
195 del _errok, _token, _restart
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/graphql/parser.pyc in p_error(self, token)
581 self.raise_syntax_error(
582 'Syntax error at %s' % repr(fragment),
--> 583 token=token,
584 )
585
/Users/rigdon/.virtualenvs/gqltest/lib/python2.7/site-packages/graphql/parser.pyc in raise_syntax_error(self, message, token)
596 value=token.value,
597 line=token.lineno,
--> 598 column=column,
599 )
SyntaxError: Line 9: Syntax error at 'fragment'
In [41]: query = """
query FragmentQuery{
hero {
name
...DroidFields
}
}
fragment DroidFields on Droid {
primaryFunction
}
"""
In [42]: doc = parser.parse(query)
In [43]: print(doc)
<Document: definitions=[<Query: name=FragmentQuery, selections=[<Field: selections=[<Field: name=name>, <FragmentSpread: name=DroidFields>], name=hero>]>, <FragmentDefinition: type_condition=<NamedType: name=Droid>, name=DroidFields, selections=[<Field: name=primaryFunction>]>]>
Is there a simple method to convert a parser AST object back into its corresponding GraphQL string? Possibly after some manipulation of the AST. Example:
>>> parser = graphql.parser.GraphQLParser()
>>> s = parser.parse("""{systems(first: 10) {
... edges {
... node {
... id
... }
... }
... }}""")
>>> s
<Document: definitions=[<Query: selections=[<Field: name=systems, arguments=[<Argument:
name=first, value=10>], selections=[<Field: name=edges, selections=[<Field: name=node, selections=
[<Field: name=id>]>]>]>]>]>
>>> graphql.render(s)
{systems(first: 10) {
edges {
node {
id
}
}
}}
I guess I could tweak all the __repr___
methods in such a way, but it seems that I am missing something?
When parsing a GraphQL document, special inputs (true
, false
, null
) should be parsed differently from "true"
, "false"
, and "null"
and should instead be returned as True
, False
, None
instead of strings.
e.g.
{
field (name: null) {
field2
}
}
should return an argument of None
{
field (name: "null") {
field2
}
}
should return an argument of "null"
The module name graphql
when doing the import is very generic and collides with other packages I'm using. If you plan some evolutions in the future, I would suggest to change it to something more specific such as graphqlparser
or similar...
Thanks for this good package!
Example query using variables fails parsing
query getZuckProfile($devicePicSize: Int) {
user(id: 4) {
id
name
profilePic(size: $devicePicSize)
}
}
with Invalid query: Line 1, col 36: Syntax error at u':'
It looks like this library doesn't support having operation names as part of the query. For example, this works:
{
hero {
name
}
}
while this does not:
query {
hero {
name
}
}
Both should be valid according to the spec.
I got this warning while using this library (version 0.8.1), is there something that can be done ?
{
episode (number: null) {
name
}
}
Returns error
"Parse error: Line 2: Syntax error at 'null'"
I was able to fix the parse error locally with the following changes:
In parser.py
on line 444
def p_const_value(self, p):
"""
const_value : INT_VALUE
| FLOAT_VALUE
| STRING_VALUE
| boolean_value
| enum_value
| const_list_value
| const_object_value
| NULL <--- Added this line
"""
and on line 431
def p_value(self, p):
"""
value : variable
| INT_VALUE
| FLOAT_VALUE
| STRING_VALUE
| boolean_value
| enum_value
| list_value
| object_value
| NULL <--- Added this line
"""
And in Lexer.py
on line 172
@TOKEN('null' + not_followed_by_name)
def t_NULL(self, t):
t.value = None <--- Added this line
return t
I'm not sure if that is the right way for the parser to recognize 'null' as None. Maybe there should be a null_value
token in addition to NULL
.
Values of string types will be returned as "_value_"
rather than _value_
(the string actually contains the "
used to delimit it.
Is this intentional?
The parser crashes when I pass a query like this one:
{
queues(filter: {name: "MOVE_LOTS"}) {
name
jobs(
filter: {
input: {contains: "{\"toResource\": \"UNCASTING_1\"}"}
}
orderBy: {desc: ID},
limit: 10
) {
id
insertedAt
queue {
id
name
}
jobStatus
input
context
output
}
}
}
the line #7 fails with this stack trace:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/graphql/parser.py", line 36, in parse
return self.yacc.parse(input=input, lexer=lexer, **kwargs)
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/ply/yacc.py", line 333, in parse
return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/ply/yacc.py", line 1201, in parseopt_notrack
tok = call_errorfunc(self.errorfunc, errtoken, self)
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/ply/yacc.py", line 192, in call_errorfunc
r = errorfunc(token)
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/graphql/parser.py", line 647, in p_error
self.raise_syntax_error(
File "/Users/baruc/.local/share/virtualenvs/pygqlc-8iu9ltOc/lib/python3.10/site-packages/graphql/parser.py", line 660, in raise_syntax_error
raise SyntaxError(
graphql.exceptions.SyntaxError: Line 7: Syntax error at ': '
When parsing a mutation I get:
File "./internal/gqlparser/parser.py", line 166, in p_operation_definition8
p[0] = self.operation_cls(p[1])(selections=p[2])
TypeError: __init__() missing 1 required positional argument: 'name'
I can see the GraphQLParser
class has operation_cls
which is looking for operation_type == 'mutation':
so I assume this module is built to parse mutations as well as queries?
I can't see a mutation example in the tests or README, is here something I'm missing? Or should this work?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.