sgqlc
sgqlc copied to clipboard
operation codegen failing on boolean literals
The first query (boolean literal) fails to generate with ValueError: not enough values to unpack (expected 3, got 1)
while the second form succeeds:
FAILS:
query MyQuery {
things(where: { global: { _eq: true } }) {
id
}
}
SUCCEEDS
query MyQuery($global: Boolean!) {
things(where: { global: { _eq: $global } }) {
id
}
}
Full traceback:
Traceback (most recent call last):
File "/Users/rory/code/github/Cogitai/sai/.venv/bin/sgqlc-codegen", line 8, in <module>
sys.exit(main())
File "/Users/rory/code/github/Cogitai/sai/.venv/lib/python3.9/site-packages/sgqlc/codegen/__init__.py", line 130, in main
args.func(args)
File "/Users/rory/code/github/Cogitai/sai/.venv/lib/python3.9/site-packages/sgqlc/codegen/operation.py", line 934, in handle_command
gen.write()
File "/Users/rory/code/github/Cogitai/sai/.venv/lib/python3.9/site-packages/sgqlc/codegen/operation.py", line 811, in write
self.write_operations()
File "/Users/rory/code/github/Cogitai/sai/.venv/lib/python3.9/site-packages/sgqlc/codegen/operation.py", line 831, in write_operations
self.write_operation(source)
File "/Users/rory/code/github/Cogitai/sai/.venv/lib/python3.9/site-packages/sgqlc/codegen/operation.py", line 841, in write_operation
for kind, name, code in thing:
ValueError: not enough values to unpack (expected 3, got 1)
could you confirm the graphql-core
version you're using?
I'm on 3.1.5 (also happens on 3.1.6)
ok, I'll take a look, but kinda overloaded at work nowadays. If you could reproduce that with the existing examples, it would help me a lot, ex https://github.com/profusion/sgqlc/tree/master/examples/github
very likely it's in the return of the leave_*
methods of GraphQLToPython
.
This specific trace is https://github.com/profusion/sgqlc/blob/master/sgqlc/codegen/operation.py#L833-L841
Which should be getting the tuple returned here: https://github.com/profusion/sgqlc/blob/master/sgqlc/codegen/operation.py#L520-L527
but seems this is not the case, since it's returning a single value, not the tuple with the 3 arguments... 🤔
@barbieri thanks for taking a look, i'll try debug further & report back!
@worrel would you mind checking if it's still happening? Many fixes to handle input, maybe it was fixed?
Hi, @barbieri . I think I'm facing the same issue.
When I run this command:
sgqlc-codegen operation my_schema ./operations/dataset.py /home/georvic/repos/datahub/datahub-web-react/src/graphql/dataset.graphql
with the following file: https://github.com/datahub-project/datahub/blob/master/datahub-web-react/src/graphql/dataset.graphql
I see the following output:
Traceback (most recent call last):
File "/home/georvic/anaconda3/envs/datahub/bin/sgqlc-codegen", line 8, in <module>
sys.exit(main())
File "/home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/__init__.py", line 130, in main
args.func(args)
File "/home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py", line 949, in handle_command
gen.write()
File "/home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py", line 826, in write
self.write_operations()
File "/home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py", line 846, in write_operations
self.write_operation(source)
File "/home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py", line 856, in write_operation
for kind, name, code in visit(gql, visitor):
ValueError: not enough values to unpack (expected 3, got 1)
When taking a look in the dataset.graphql file, I can see the following: https://github.com/datahub-project/datahub/blob/master/datahub-web-react/src/graphql/dataset.graphql#L114
autoRenderAspects: aspects(input: { autoRenderOnly: true }) {
aspectName
payload
renderSpec {
displayType
displayName
key
}
}
So, it seems the same issue.
My versions are:
sgqlc==16.2 Python 3.7.16 graphql-core==3.2.3
Notes:
If I replace the true by a false, I get the following output in the python file:
_frag_auto_render_aspects = _frag.aspects(input={'autoRenderOnly': BooleanValueNode at 2402:2407}, __alias__='auto_render_aspects')
If I place a breakpoint here:
I get the following output in pdb
(Pdb) res = list(visit(gql, visitor))
(Pdb) res
['a', 'u', 't', 'o', 'R', 'e', 'n', 'd', 'e', 'r', 'O', 'n', 'l', 'y']
hi, could you check with graphql-core==3.1.6
? I bet the error is there, if that's the case I'll need to check how to make a code that works in both or just bump the minimum requirement to be that version (since it's out since september 2022, almost one year old).
sorry, edited the last msg, it's 3.1.6 that should be tested.
Looking at https://github.com/datahub-project/datahub/blob/master/datahub-web-react/src/graphql/dataset.graphql#L114 what calls attention is the usage of an alias (autoRenderAspects
), we should be handling them correctly at https://github.com/profusion/sgqlc/blob/master/sgqlc/codegen/operation.py#L651-L671
alias = ''
if node.alias:
alias = to_python_name(node.alias)
args = list(args) + [('__alias__', alias)]
could you please check this part? Also, if you can print the kind
at https://github.com/graphql-python/graphql-core/blob/main/src/graphql/language/visitor.py#L145-L153, we could see if there is something we're missing.
Hi, @barbieri . Thanks for taking a look. Yes, it also happens with that version:
For this version, I don't see the get_enter_leave_for_kind function.
If I use the version I tested originally, I do find the function. After placing a print call, I get the following:
So, the last element before the exception is: boolean_value
If I place a breakpoint here using an if:
, I get the following:
(Pdb) enter_leave
EnterLeaveVisitor(enter=None, leave=<bound method GraphQLToPython.leave_boolean_value of <sgqlc.codegen.operation.GraphQLToPython object at 0x7eff0170abd0>>)
(Pdb)
and these are all the steps shown in the debugger until the exception occurs:
Click here to expand all the pdb steps (just pressing n until the exception appears)
(datahub) georvic@georvic-IdeaPad-3-15ITL6:~/repos/datahub-metadata$ sgqlc-codegen operation my_schema ./operations/dataset.py /home/georvic/repos/datahub/datahub-web-react/src/graphql/dataset.graphql
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(140)get_enter_leave_for_kind()
-> enter_fn = getattr(self, f"enter_{kind}", None)
(Pdb) print(kind)
boolean_value
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(141)get_enter_leave_for_kind()
-> if not enter_fn:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(142)get_enter_leave_for_kind()
-> enter_fn = getattr(self, "enter", None)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(143)get_enter_leave_for_kind()
-> leave_fn = getattr(self, f"leave_{kind}", None)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(144)get_enter_leave_for_kind()
-> if not leave_fn:
(Pdb) leave_fn
<bound method GraphQLToPython.leave_boolean_value of <sgqlc.codegen.operation.GraphQLToPython object at 0x7eff0170abd0>>
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(146)get_enter_leave_for_kind()
-> enter_leave = EnterLeaveVisitor(enter_fn, leave_fn)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(147)get_enter_leave_for_kind()
-> self.enter_leave_map[kind] = enter_leave
(Pdb) enter_leave
EnterLeaveVisitor(enter=None, leave=<bound method GraphQLToPython.leave_boolean_value of <sgqlc.codegen.operation.GraphQLToPython object at 0x7eff0170abd0>>)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(148)get_enter_leave_for_kind()
-> return enter_leave
(Pdb) self.enter_leave_map[kind]
EnterLeaveVisitor(enter=None, leave=<bound method GraphQLToPython.leave_boolean_value of <sgqlc.codegen.operation.GraphQLToPython object at 0x7eff0170abd0>>)
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(148)get_enter_leave_for_kind()->EnterLeaveVis...eff0170abd0>>)
-> return enter_leave
(Pdb) list
143 leave_fn = getattr(self, f"leave_{kind}", None)
144 if not leave_fn:
145 leave_fn = getattr(self, "leave", None)
146 enter_leave = EnterLeaveVisitor(enter_fn, leave_fn)
147 self.enter_leave_map[kind] = enter_leave
148 -> return enter_leave
149
150 def get_visit_fn(
151 self, kind: str, is_leaving: bool = False
152 ) -> Optional[Callable[..., Optional[VisitorAction]]]:
153 """Get the visit function for the given node kind and direction.
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(261)visit()
-> visit_fn = enter_leave.leave if is_leaving else enter_leave.enter
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(262)visit()
-> if visit_fn:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(282)visit()
-> result = None
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(284)visit()
-> if result is None and is_edited:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(287)visit()
-> if is_leaving:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(291)visit()
-> stack = Stack(in_array, idx, keys, edits, stack)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(292)visit()
-> in_array = isinstance(node, tuple)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(293)visit()
-> keys = node if in_array else visitor_keys.get(node.kind, ())
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(294)visit()
-> idx = -1
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(295)visit()
-> edits = []
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(296)visit()
-> if parent:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(297)visit()
-> ancestors_append(parent)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(298)visit()
-> parent = node
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(300)visit()
-> if not stack:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(216)visit()
-> idx += 1
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(217)visit()
-> is_leaving = idx == len(keys)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(218)visit()
-> is_edited = is_leaving and edits
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(219)visit()
-> if is_leaving:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(220)visit()
-> key = path[-1] if ancestors else None
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(221)visit()
-> node = parent
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(222)visit()
-> parent = ancestors_pop() if ancestors else None
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(223)visit()
-> if is_edited:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(239)visit()
-> idx = stack.idx
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(240)visit()
-> keys = stack.keys
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(241)visit()
-> edits = stack.edits
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(242)visit()
-> in_array = stack.in_array
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(243)visit()
-> stack = stack.prev
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(255)visit()
-> if isinstance(node, tuple):
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(258)visit()
-> if not isinstance(node, Node):
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(260)visit()
-> enter_leave = visitor.get_enter_leave_for_kind(node.kind)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(261)visit()
-> visit_fn = enter_leave.leave if is_leaving else enter_leave.enter
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(262)visit()
-> if visit_fn:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(263)visit()
-> result = visit_fn(node, key, parent, path, ancestors)
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(265)visit()
-> if result is BREAK or result is True:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(266)visit()
-> break
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(303)visit()
-> if edits:
(Pdb) n
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(304)visit()
-> return edits[-1][1]
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/graphql/language/visitor.py(304)visit()->'autoRenderOnly'
-> return edits[-1][1]
(Pdb) n
ValueError: not enough values to unpack (expected 3, got 1)
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(857)write_operation()
-> for kind, name, code in visit(gql, visitor):
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(857)write_operation()->None
-> for kind, name, code in visit(gql, visitor):
(Pdb) n
ValueError: not enough values to unpack (expected 3, got 1)
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(846)write_operations()
-> self.write_operation(source)
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(846)write_operations()->None
-> self.write_operation(source)
(Pdb) n
ValueError: not enough values to unpack (expected 3, got 1)
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(826)write()
-> self.write_operations()
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(826)write()->None
-> self.write_operations()
(Pdb) n
ValueError: not enough values to unpack (expected 3, got 1)
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(950)handle_command()
-> gen.write()
(Pdb) n
--Return--
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/operation.py(950)handle_command()->None
-> gen.write()
(Pdb) n
ValueError: not enough values to unpack (expected 3, got 1)
> /home/georvic/anaconda3/envs/datahub/lib/python3.7/site-packages/sgqlc/codegen/__init__.py(130)main()
It seems that the visit function returns at: https://github.com/graphql-python/graphql-core/blob/0c93b8452eed38d4f800c7e71cf6f3f3758cd1c6/src/graphql/language/visitor.py#L298
edits looks like ``[('name', 'autoRenderOnly')] and edits[-1][1] is returned
hum, the damn bug should be here in the graphql-core (from your backtrace above):
if result is BREAK or result is True:
break
if result is SKIP or result is False:
if not is_leaving:
path_pop()
continue
as we process a boolean replacing it with True
or False
, we enter these blocks. I'll see how to solve this, likely as I had to do with None
:
# Use Null instead of None as Visitor.leave_* understands None as IDLE,
# which keeps the original node.
class Null:
def __repr__(self):
return 'None'