Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursively finding implemented interfaces #124

Closed
LWprogramming opened this issue Mar 18, 2021 · 4 comments
Closed

Recursively finding implemented interfaces #124

LWprogramming opened this issue Mar 18, 2021 · 4 comments

Comments

@LWprogramming
Copy link

Given a GraphQL schema with interface types and types that implement interfaces, it's possible to have a "chain" of implementations. For instance, a schema might have an interface Entity implemented by the interface LivingEntity, which is then implemented by the interface Animal, which is in turn implemented by the object type Dog.

Given the ObjectTypeDefinitionNode for Dog in the schema (e.g. while using a visitor object), is there a way to find all interfaces it implements (i.e. {Entity, LivingEntity, Animal}? Right now, the ObjectTypeDefinitionNode's interfaces field is a NamedTypeNode list rather than an InterfaceTypeDefinitionNode list. That makes it impossible to use the interfaces field to do this recursively, since we'd find the NamedTypeNode for Animal and have no way of finding the InterfaceTypeDefinitionNode for Animal.

The GraphQLSchema type does have a private field named _implementations_map dictionary, but this is a mapping from interface to implementation, rather than the other way around.

@Cito
Copy link
Member

Cito commented Mar 19, 2021

As you already noticed, the interfaces attribute of the node gives you the NamedTypeNodes in the SDL, corresponding to the name list after the "implements" keyword. To find the corresponding interface definitions, you need to look them up in the definitions list of the document. E.g.

import graphql

ast = graphql.parse(
    """
    type Dog implements Animal {
      name: String
    }

    interface Animal implements LivingEntity {
      name: String
    }

    interface LivingEntity implements Entity {
      name: String
    }

    interface Entity {
      name: String
    }

    type Query {
      dogs: [Dog]
    }
    """)

interface_defs = {node.name.value: node
  for node in ast.definitions
  if node.kind == 'interface_type_definition'}

def show_interfaces(node, level=0):
  print("  " * level, node.name.value)
  for i in node.interfaces:
    i = interface_defs[i.name.value]
    show_interfaces(i, level + 1)

show_interfaces(ast.definitions[0])

When implementing a validation rule visitor, you can use the validation context to access the definitions.

@LWprogramming
Copy link
Author

Thanks! The definitions field is exactly what I was looking for. It seems like this doesn't have a comment attached to it in read-the-docs-- do we expect this field to stay around long-term? If so, I'd be happy to open a short PR describing what it does.

@Cito
Copy link
Member

Cito commented Mar 19, 2021

The node attributes in GraphQL-core mimic the node properties in GraphQL.js. As far as I see, these properties are part of the external interface of GraphQL.js, so I don't expect them to change (but you can ask the GraphQL.js project to be sure). They generally do not have docstrings, since in GraphQL.js they are also not documented. I would not want to start adding a docstring here for a single attribute, since then we should document all of them. Also as always I would prefer that the docstrings are added to GraphQL.js and then ported here.

@LWprogramming
Copy link
Author

Got it. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants