profusion / sgqlc

Simple GraphQL Client
https://sgqlc.readthedocs.io/
ISC License
513 stars 85 forks source link

retrieve list of files in GitHub repo #98

Closed m27315 closed 4 years ago

m27315 commented 4 years ago

Sorry, I couldn't think of a better title, because it represents my exact use case. ... How could I realize the following GraphQL query?

{
  organization(login: "MyOrganization") {
    repository(name: "MyRepoName") {
      id
      databaseId
      name
      description
      descriptionHTML
      homepageUrl
      shortDescriptionHTML
      nameWithOwner
      openGraphImageUrl
      resourcePath
      sshUrl
      url
      defaultBranchRef {
        name
      }
      object(expression: "master:") {
        ... on Tree {
          entries {
            name
            type
            oid
            mode
          }
        }
      }
    }
  }
}

The hard part is the Tree.entries:

object(expression: "master:") {
        ... on Tree {
          entries {
            name
            type
            oid
            mode
          }
        }

Currently, I have something like this:

        op = Operation(schema.Query, end_cursor=str)
        orgid = op.organization(login=org)
        rid = orgid.repository(name=repo)
        brid = rid.object(expression="master:")
        obj = brid.object(first=100, after=Variable("end_cursor"))
        obj.entries.oid()
        obj.entries.name()
        obj.entries.type()
        obj.entries.mode()
        obj.page_info.__fields__("has_next_page", "end_cursor")
        return op
barbieri commented 4 years ago

You need to use fragments as well, see https://sgqlc.readthedocs.io/en/latest/sgqlc.operation.html#inline-fragments-interfaces


as_tree = obj.__as__(Tree)
as_tree.name()
as_tree.type()
as_tree.oid()

something like this should work. The resulting graphql (once printed) should match the yours and when reading it back it will automatically check __typename to detect if it's a Tree, in such case it will instantiate that object instead of the generic interface or union.

Let me know if that works, if so paste the solution for further reference :-)

m27315 commented 4 years ago

Thanks for the quick response and help, @barbieri! Based on your suggestion, here's the solution I used:

op = Operation(schema.Query)
orgid = op.organization(login="MyOrganization")
rid = orgid.repository(name="MyRepoName")
brid = rid.object(expression="master:")
as_tree = brid.__as__(schema.Tree)
entries = as_tree.entries()
entries.name()
entries.type()
entries.oid()

It appears that no cursor or pageInfo is supported on these, so I deleted references to that.

Ultimately, I'd like to make this recursive, so I could get all of the file names for a given repo, but this is a good start.

Thanks again, @barbieri!

barbieri commented 4 years ago

There is no real recursion in GraphQL, so you need to expand "up to a level", then you can simply use a function that takes a selector as parameter and selects the fields and then call itself, reducing a counter so it knows when to stop.