Skip to main content

A simplified, opinionated way to access the GitHub GraphQL API

Project description

GitHubGQL

GitHubGQL provides a simplified, opinionated way to access the GitHub GraphQL API, particularly with respect to handling paging.

Overview

Given a complex, nested query with multiple levels of collections, a standard GQL query to the GitHub API must contain and request instrumentation to manage paging information. This information includes cursors, the total number of elements to expect, and notification of whether or not the request has a next page. In order to complete a request, the client must request additional pages in a bottom-up manner throughout the query graph, only incrementing a cursor when all cursors below it are completed, then reset the lower cursors to their beginning.

Additionally, the GitHub GQL organizes collections into edges and nodes, facilitating true graph navigation. For common use, these edges and nodes can be implicit, allowing the client to speak only in terms of collections of objects. Thus, the following query:

query deeplyNestedQuery {
    viewer {
        id
        login
        email
        repositories(first: 5, after: null) {
            edges {
                node {
                    id
                    name
                    description
                    assignableUsers(first: 5, after: null) {
                        edges {
                            node {
                                id
                                login
                                isViewer
                                contributionsCollection(first: 5, after: null) {
                                    edges {
                                        node {
                                            commitContributionsByRepository(first: 5, after: null, maxRepositories: 5) {
                                                edges {
                                                    node {
                                                        repository {
                                                            id
                                                            name
                                                            createdAt
                                                        }
                                                    }
                                                    cursor
                                                }
                                                pageInfo {
                                                    endCursor
                                                    hasNextPage
                                                }
                                                totalCount
                                            }
                                        }
                                        cursor
                                    }
                                    pageInfo {
                                        endCursor
                                        hasNextPage
                                    }
                                    totalCount
                                }
                            }
                            cursor
                        }
                        pageInfo {
                            endCursor
                            hasNextPage
                        }
                        totalCount
                    }
                }
                cursor
            }
            pageInfo {
                endCursor
                hasNextPage
            }
            totalCount
        }
    }
}

…could potentially be reduced to:

query deeplyNestedQuery($maxContributionsRepos: Int) {
    viewer {
        email
        repositories {
            description
            assignableUsers {
                isViewer
                contributionsCollection {
                    commitContributionsByRepository(maxRepositories: $maxContributionsRepos) {
                        repository {
                            createdAt
                        }
                    }
                }
            }
        }
    }
}

In addition to the paging information, the previous example illustrates a separate feature of GitHubGQL. Each collection will automatically fetch a small subset of fields inherent to its identification. Thus where the first query requests fields like id, name, or login, the second can omit those fields and only list non-ID fields like isViewer and createdAt.

Install

pip install GitHubGQL

Usage

Get All Data at Once

from githubgql.Client import GitHubGQL

query = '''
query deeplyNestedQuery($maxContributionsRepos: Int) {
    viewer {
        email
        repositories {
            description
            assignableUsers {
                isViewer
                contributionsCollection {
                    commitContributionsByRepository(maxRepositories: $maxContributionsRepos) {
                        repository {
                            createdAt
                        }
                    }
                }
            }
        }
    }
}
'''
vars = {'maxContributionsRepos': 5}

client = GitHubGQL()  # Scrapes Personal Access Token from `git config --get
                      # user.password` and uses default_page_size of 100
results = client.execute_all(query, vars)

Paged Data via Iterator

from githubgql.Client import GitHubGQL

# ...same query and vars as above...

pat = get_my_personal_access_token()  # exercise for the reader
client = GitHubGQL(pat, default_page_size=47)

merged_results = {}
for result in client.execute_iter():
    GitHubGQL.Merger.merge(merged_results, result)
    if next((x for x in result['viewer']['repositories'] if x['name'] == 'bgm-nerdrock'), False):
        # Got what we need; use it
        break

Paged Data via Callback

from githubgql.Client import GitHubGQL

# ...same query and vars as above...

pat = get_my_personal_access_token()  # exercise for the reader
client = GitHubGQL(pat)  # default_page_size of 100

merged_results = {}

def callback(result):
    GitHubGQL.Merger.merge(merged_results, result)
    if next((x for x in result['viewer']['repositories'] if x['name'] == 'bgm-nerdrock'), False):
        # Got what we need; use it
        return False
    return True

client.execute_callback(callback)

Documentation

In progress, stay tuned for docs site

Development

Contributing

Long-term discussion and bug reports are maintained via GitHub Issues. Code review is done via GitHub Pull Requests.

For more information read CONTRIBUTING.md.

Maintainership

Until this project gets any traction at all, no need for maintainers

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

github_graphql_paginator-0.0.1.tar.gz (200.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

github_graphql_paginator-0.0.1-py3-none-any.whl (208.0 kB view details)

Uploaded Python 3

File details

Details for the file github_graphql_paginator-0.0.1.tar.gz.

File metadata

  • Download URL: github_graphql_paginator-0.0.1.tar.gz
  • Upload date:
  • Size: 200.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.0

File hashes

Hashes for github_graphql_paginator-0.0.1.tar.gz
Algorithm Hash digest
SHA256 fb95507e95ab63dcfbfbe4c0c425cc9413141623722b77aa9f5934a2ca8c13a2
MD5 74b09402fda9c572444a41278096ac28
BLAKE2b-256 4d2d9c3b108ac91a610bdf810975fec3f807e55a791e2b702e756e68311aba41

See more details on using hashes here.

File details

Details for the file github_graphql_paginator-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for github_graphql_paginator-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3e38d699bd3e75217857cb61d9682e60e2e10a6b77e4dcb1fcc47a4edf502474
MD5 2f1a188ad717612a796a96a34a8de4f1
BLAKE2b-256 dee7e324c2afafeac28ed65d69e7488a2ad6a930af0a7541637fe6a081eee24c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page