graphql-python / gql

A GraphQL client in Python

Home Page:https://gql.readthedocs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DSL, Fragments and unions

FrankC01 opened this issue · comments

This works in an online query tool:

  transactionBlock(digest:"CypToNgx6jN2V6vDZGtgpeEv1zSs4VGJcANJi85w9Ypm") {
    digest
    kind {
      __typename
      ... on ProgrammableTransaction {
        value
      }
      ... on GenesisTransaction {
        objects 
      }
    }
}

However I can't figure out the DSL Fragment for handling the union. If I have one of the union types it works fine:

STANDARD_TRANSACTION_KIND: DSLFragment = (
    DSLFragment("TransactionUnion")
    .on(SUI_GRAPHQL_SCHEMA.ProgrammableTransaction)
    .select(SUI_GRAPHQL_SCHEMA.ProgrammableTransaction.value)
)

However; not sure how to handle all cases. Do I need to declare a fragment for all union types? And, if so, do I just comma separate them in the query?

Also, sorry if this is not the place for questions... please direct me otherwise.

What you have here in your query is an inline fragment.

To reproduce that query using DSL, you should then use DSLInlineFragment, and yes, you should have one inline fragment for each union type for which you want to retrieve data. You can select multiple DSLInlineFragment in a select method, as arguments of the method, so separated by commas.

Using DSLFragment is also an option if you want to have separated named fragments that you can reuse but the query will be different.

Great, i saw that in DSLFragment I can chain '.on(...)` so I had assumed I could 1 fragment for all union variants.

No problem and thanks for the solution, I missed the inline fragment entirely.

One last question. This works with the __typename select on the union commented out:

            self.schema.TransactionBlock.kind.select(
                # TODO: Need correct way to fetch this
                # self.schema.TransactionBlockKind.__typename,
                DSLInlineFragment()
                .on(self.schema.ProgrammableTransaction)
                .select(
                    self.schema.ProgrammableTransaction.value,
                ),
                DSLInlineFragment()
                .on(self.schema.GenesisTransaction)
                .select(self.schema.GenesisTransaction.objects),
            )

Here is the union from the schema:
union TransactionBlockKind = ConsensusCommitPrologueTransaction | GenesisTransaction | ChangeEpochTransaction | ProgrammableTransaction | AuthenticatorStateUpdate | EndOfEpochTransaction

When I uncomment it I get:

  File "/Users/fastfrank/frankc01/pysui-gql/pgql/pysui_ql_builders.py", line 142, in build
    self.schema.TransactionBlockKind.__typename,
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/fastfrank/.local/share/virtualenvs/pysui-gql-kXYEURx6/lib/python3.11/site-packages/gql/dsl.py", line 298, in __getattr__
    assert isinstance(type_def, (GraphQLObjectType, GraphQLInterfaceType))
AssertionError

Never mind, I'm using DSLMetaField for that and all is good.