Skip to content

Instantly share code, notes, and snippets.

@gbaman
Created November 1, 2017 00:18
Show Gist options
  • Save gbaman/b3137e18c739e0cf98539bf4ec4366ad to your computer and use it in GitHub Desktop.
Save gbaman/b3137e18c739e0cf98539bf4ec4366ad to your computer and use it in GitHub Desktop.
An example on using the Github GraphQL API with Python 3
# An example to get the remaining rate limit using the Github GraphQL API.
import requests
headers = {"Authorization": "Bearer YOUR API KEY"}
def run_query(query): # A simple function to use requests.post to make the API call. Note the json= section.
request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers)
if request.status_code == 200:
return request.json()
else:
raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))
# The GraphQL query (with a few aditional bits included) itself defined as a multi-line string.
query = """
{
viewer {
login
}
rateLimit {
limit
cost
remaining
resetAt
}
}
"""
result = run_query(query) # Execute the query
remaining_rate_limit = result["data"]["rateLimit"]["remaining"] # Drill down the dictionary
print("Remaining rate limit - {}".format(remaining_rate_limit))
@SamsonEshipillahPasili
Copy link

Saved me hours of frustration.... Thank you!

@janvanmansum
Copy link

Thanks, exactly what I needed! 👍

@Hansanhoo
Copy link

👍

@digizeph
Copy link

digizeph commented Jan 2, 2020

Thank you!

@theitush
Copy link

Awesome, thanks!

@BasuRB
Copy link

BasuRB commented Feb 3, 2020

If you're using a Personal Access Token (PAT), you need to put the word "token" or "bearer" before the actual token:
headers = {"Authorization": "token XYZ123TOKENTOKENTOKEN"}

Thanks!

@saurav-bhagat
Copy link

Hey, thanks for this post. Can we enable auto completion or graphiql like features while making these kinds of requests from notebook?

@johnmee
Copy link

johnmee commented Mar 5, 2020

Mutations are the same.

May I mention that the part where it says json={'query': query} does not vary regardless of whether it is a query or mutation. So, yes, it does end up with {"query": { "query"... or {"query": {"mutation":...

@mrpbennett
Copy link

👍 amazing thank you...just what I was looking for.

@prcurran
Copy link

prcurran commented Sep 3, 2020

This is just what I needed - thanks!

@sct10876
Copy link

so cool, exactly what I need, thank you!

@JGutierrezG
Copy link

Easy to read, flexible and still works in 2021, thanks for this!!!!

@ItaloQualisoni
Copy link

thanks!

@paramasivan1
Copy link

How do I paginate thru results in python code?

@JGutierrezG
Copy link

JGutierrezG commented Apr 13, 2021

How do I paginate thru results in python code?

Hello!!
Hopefully my solution works for you
I did something like this:

def run_query():  # A simple function to use requests.post to make the API call. Note the json= section.
    end_cursor = ""
    users_list = []
    while True:
        has_next_page = False
        query = """
        {
        organization(login:"[YOUR_ORG]") {
            samlIdentityProvider{
              externalIdentities(first:100""" + end_cursor + """){
                pageInfo {
                          startCursor
                  hasNextPage
                        endCursor
                        }
                nodes{
                  samlIdentity{
                    nameId
                    username
                  }
                  user{
                    login
                    id
                    name
                    email
                  }
                }
              }
            }
          }
        }
        """
        request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers)
        if request.status_code == 200:
            result = request.json()
            has_next_page = (result["data"]["organization"]
                                   ['samlIdentityProvider']
                                   ['externalIdentities']['pageInfo']
                                   ['hasNextPage'])
            new_cursor = (result["data"]["organization"]
                                ['samlIdentityProvider']
                                ['externalIdentities']['pageInfo']
                                ['endCursor'])
            result_data = (result["data"]["organization"]
                                 ['samlIdentityProvider']
                                 ['externalIdentities']['nodes'])
            if has_next_page:
                end_cursor = ', after:"' + new_cursor + '"'
            else:
                break
        else:
            raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))
    return

@malli1246
Copy link

To pass in variables to the query you need to:

  • add variables parameter in your run_query function.
  • add variables key to the json you that is going to be appended to the graphql endpoint
  • create the variables dictionary with the parameters you want to pass

my python is a bit rusty but this works

import requests

class graphQL:

	headers = {"Authorization": "token <token_here>"}

	"""docstring for graphQL"""
	def __init__(self):
		super(graphQL, self).__init__()

	def run_query(self, query, variables): # A simple function to use requests.post to make the API call. Note the json= section.
		request = requests.post('https://api.github.com/graphql', json={'query': query, 'variables': variables}, headers=self.headers)
		if request.status_code == 200:
			return request.json()
		else:
			raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))
	


	def getClosedIssuesActors(self):
		listOfNames = []
		query = '''
			query($owner: String!, $name: String!) { 
				repository(owner: $owner, name: $name){
				  issues(states: CLOSED, first:10){
					edges{
					  node{
						... on Issue{
						  timeline(last: 100){
							edges{
							  node{
								__typename
								... on ClosedEvent{
								  actor{
									login
								  }
								}
							  }
							}
						  }
						}
					  }
					}
				  }
				}
			}'''

		variables = {
  			"owner": "tatmush",
  			"name": "Saturday-THORN-Dev-Rank"
		}	

		result = self.run_query(query, variables) #execute query
		print(result)

don't forget to declare the variables in the query itself.

This approach saved a lot of time for me. thank you for sharing this

@milahu
Copy link

milahu commented Oct 14, 2021

query = """
{
  rateLimit {
    limit
    cost
    remaining
    resetAt
  }
}
"""

is not necessary. the ratelimit status is sent in every response.headers

import requests
from datetime import datetime, timezone
import time

github_token = 'ghp_xxxxxxxxxxxxxxxxxxxx'

real_requests_post = requests.post
def wrap_requests_post(*args, **kwargs):
    if not 'headers' in kwargs:
        kwargs['headers'] = {}
    kwargs['headers']['Authorization'] = 'token ' + github_token
    response = real_requests_post(*args, **kwargs)
    if 'x-ratelimit-used' in response.headers._store:
        print("ratelimit status: used %s of %s. next reset in %s minutes" % (
            response.headers['X-RateLimit-Used'],
            response.headers['X-RateLimit-Limit'],
            datetime.fromtimestamp(int(response.headers["X-RateLimit-Reset"]) - time.time(), tz=timezone.utc).strftime("%M:%S")
        ))
    return response
requests.post = wrap_requests_post

query = """
{ viewer { starredRepositories(first: 5) {
    nodes { name nameWithOwner sshUrl description }
    pageInfo { endCursor hasNextPage }
} } }
"""
response = requests.post('https://api.github.com/graphql', json={'query': query})
data = response.json()

sample output

ratelimit status: used 8 of 5000. next reset in 43:57 minutes

@waltertschwe
Copy link

For anyone trying to pass variables for these queries, I suggest looking at string.Template in python:

from string Import Template
queryTemplate = Template(
"""{
  viewer {
    repositories(first: $num) {
      pageInfo {
        hasNextPage
        endCursor
      }
      edges {
        node {
          name
        }
      }
    }
  }
}"""
)

query = queryTemplate.substitute(num=n)

@Zylvian @deepaksisodiya

This worked well. thx!

@els-pnw
Copy link

els-pnw commented May 27, 2022

Is there a way to search for all issues across an org? Using REST I would do https://api.github.com/search/issues?q=user:{org_name}&per_page=100&page=1 Any help reformatting this for Graphql would be appreciated.

@SD-13
Copy link

SD-13 commented Jul 13, 2023

@els-pnw I was trying to find a way of doing it with graphql explorer but got stuck for this error

"message": "Although you appear to have the correct authorization credentials, the kubernetes organization has enabled OAuth App access restrictions, meaning that data access to third-parties is limited. For more information on these restrictions, including how to enable this app, visit https://docs.github.com/articles/restricting-access-to-your-organization-s-data/"

I ended up with something like this

query ($org_name: String!) {
    organization(login: $org_name) {
        repositories(last: 3) {
            nodes {
                issues(last: 2) {
                    nodes {
                        number
                        assignees {
                            edges {
                                node {
                                    name
                                }
                            }
                        }
                        author {
                            login
                        }
                        state
                    }
                }
            }
        }
    }
}

Not sure how much it will help you, again the explorer is nice, just play with it, hope you will get your answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment