graphql-python/gql

DSL Question

FrankC01 opened this issue · 5 comments

I am using DSL module to create query

The beginning of a query that works is this:

        DSLQuery(
            qres=schema.Query.address(address=for_address).select(
                data=schema.Address.coinConnection(type="0x2::sui::SUI").select(
                     cursor=schema.CoinConnection.pageInfo.select(PAGE_CURSOR),
                # ... more here

However I need to build the initial sequentially as the there is another argument of coinConnect that I need to add conditionally.

In essense:

qres=schema.Query.address(address=for_address)
if condition:
    qres.select(data=schema.Address.coinConnection(type="0x2::sui::SUI",on_condition=condition)
else:
    qres.select(data=schema.Address.coinConnection(type="0x2::sui::SUI")

However; if I then try:

        DSLQuery(
            qres.select(
                cursor=schema.CoinConnection.pageInfo.select(PAGE_CURSOR),
                # ... more here

I get error, I'm a new user and may not be understanding something

Please post the error you received and the Graphql schema.

The error

Traceback (most recent call last):
  File "/Users/fastfrank/.pyenv/versions/3.11.4/lib/python3.11/runpy.py", line 198, in _run_module_as_main
    return _run_code(code, main_globals, None,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/fastfrank/.pyenv/versions/3.11.4/lib/python3.11/runpy.py", line 88, in _run_code
    exec(code, run_globals)
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 39, in <module>
    cli.main()
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 430, in main
    run()
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 284, in run_file
    runpy.run_path(target, run_name="__main__")
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 321, in run_path
    return _run_module_code(code, init_globals, run_name,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 135, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/Users/fastfrank/.vscode/extensions/ms-python.python-2023.20.0/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 124, in _run_code
    exec(code, run_globals)
  File "/Users/fastfrank/frankc01/pysui-gql/g1.py", line 29, in <module>
    do_gas(client_init)
  File "/Users/fastfrank/frankc01/pysui-gql/g1.py", line 13, in do_gas
    result = client.get_gas2(
             ^^^^^^^^^^^^^^^^
  File "/Users/fastfrank/frankc01/pysui-gql/pgql/gclients.py", line 38, in get_gas2
    sreads.get_gas2(for_address=address, schema=SUI_GRAPHQL_SCHEMA)
  File "/Users/fastfrank/frankc01/pysui-gql/pgql/static_reads.py", line 102, in get_gas2
    qres.select(
  File "/Users/fastfrank/.local/share/virtualenvs/pysui-gql-kXYEURx6/lib/python3.11/site-packages/gql/dsl.py", line 884, in select
    super().select(*fields, **fields_with_alias)
  File "/Users/fastfrank/.local/share/virtualenvs/pysui-gql-kXYEURx6/lib/python3.11/site-packages/gql/dsl.py", line 362, in select
    raise GraphQLError(f"Invalid field for {self!r}: {field!r}")
graphql.error.graphql_error.GraphQLError: Invalid field for <DSLField Query::address>: <DSLField CoinConnection::pageInfo>

The code

def get_gas2(*, for_address: str, schema: DSLSchema, after: str = None) -> DocumentNode:
    """Query to get gas objects owned by address

    :param for_address: The Sui address for the network
    :type for_address: str
    :param schema: The Sui RPC 2.0 schema
    :type schema: DSLSchema
    :param after: Used in paging where caller is controlling node point, optional
    :type after: str, default is None
    :return: Document Query node ready for execution
    :rtype: DocumentNode
    """

    if not after:
        qres = schema.Query.address(address=for_address).select(
            data=schema.Address.coinConnection(type="0x2::sui::SUI")
        )
    else:
        qres = schema.Query.address(address=for_address).select(
            data=schema.Address.coinConnection(type="0x2::sui::SUI", after=after)
        )

    # Query generation
    return dsl_gql(
        PAGE_CURSOR,
        DSLQuery(
            qres.select(
                cursor=schema.CoinConnection.pageInfo.select(PAGE_CURSOR),
                gas_objects=schema.CoinConnection.nodes.select(
                    schema.Coin.balance,
                    schema.Coin.asMoveObject.select(
                        schema.MoveObject.asObject.select(
                            schema.Object.version,
                            schema.Object.digest,
                            coin_object_id=schema.Object.location,
                            owner=schema.Object.owner.select(
                                owner_address=schema.Owner.location
                            ),
                        ),
                        schema.MoveObject.contents.select(
                            schema.MoveValue.type.select(coin_type=schema.MoveType.repr)
                        ),
                    ),
                ),
            )
        ),
    )

Schema attached
schema.graphql.json

your qres variable is an address type and you are selecting a pageInfo field in it, so the request you are trying to build look like:

address(...) {
    cursor: PageInfo {
        ....
    }
}

which does not correspond to the schema.

What you could do instead is something like this:

qres = schema.Query.address(address=for_address)                                                                       
                                                                                                                        
if not after:                                                                                                           
    coin_connection = schema.Address.coinConnection(type="0x2::sui::SUI")                                               
else:                                                                                                                   
    coin_connection = schema.Address.coinConnection(type="0x2::sui::SUI", after=after)                                  
                                                                                                                        
coin_connection.select(                                                                                                 
    cursor=schema.CoinConnection.pageInfo.select(PAGE_CURSOR),                                                          
    gas_objects=schema.CoinConnection.nodes.select(                                                                     
        schema.Coin.balance,                                                                                            
        schema.Coin.asMoveObject.select(                                                                                
            schema.MoveObject.asObject.select(                                                                          
                schema.Object.version,                                                                                  
                schema.Object.digest,                                                                                   
                coin_object_id=schema.Object.location,                                                                  
                owner=schema.Object.owner.select(                                                                       
                    owner_address=schema.Owner.location                                                                 
                ),                                                                                                      
            ),                                                                                                          
            schema.MoveObject.contents.select(                                                                          
                schema.MoveValue.type.select(coin_type=schema.MoveType.repr)                                            
            ),                                                                                                          
        ),                                                                                                              
    ),                                                                                                                  
)                                                                                                                       
                                                                                                                        
qres.select(coin_connection)

In fact, you could even simplify the condition like this:

coin_connection = schema.Address.coinConnection(type="0x2::sui::SUI")                                                   
                                                                                                                        
if after:                                                                                                                
    coin_connection(after=after)

Got it! Thanks for the clarification