Here is some example code to help you understand how the github3 library works. (I wrote it to help me understand how the github3 library works. I hope it helps you!)
(kind of like dir(), but nicer, in that it removes functions with double-underscores - you don't have to care about the details of this)
# public() is from here: http://nbviewer.ipython.org/gist/jiffyclub/9235955
def public(thing):
"""Print 'public' attributes of thing."""
for x in dir(thing):
if not x.startswith('_'):
print(x)
You know everything went OK if you see the message "Access granted" after running this.
import github3
# fill in your GitHub username and your preferred repository name:
my_username = ''
my_repo_name = ''
# generate a token for yourself in GitHub; paste it in below
g = github3.login(token='')
if g:
print('Access granted.')
Access granted.
# What have we just wrought?
############## return value ######################
# github3.login() returns: <GitHub at 0x104a2e910>
##################################################
# So that's a GitHub object.
if g:
print('What can be done with a GitHub object:')
print('=====================================')
public(g)
What can be done with a GitHub object: ===================================== authorization authorize check_authorization create_gist create_issue create_key create_repo delete_key emojis etag feeds follow from_json gist gitignore_template gitignore_templates is_following is_starred is_subscribed issue iter_all_repos iter_all_users iter_authorizations iter_emails iter_events iter_followers iter_following iter_gists iter_issues iter_keys iter_notifications iter_org_issues iter_orgs iter_repo_issues iter_repos iter_starred iter_subscriptions iter_user_issues iter_user_repos iter_user_teams key last_modified login markdown membership_in meta octocat organization organization_memberships pubsubhubbub pull_request rate_limit ratelimit_remaining refresh repository revoke_authorization revoke_authorizations search_code search_issues search_repositories search_users set_client_id set_user_agent star subscribe to_json unfollow unstar unsubscribe update_user user zen
This will make an actual repository in your actual account on GitHub. So... You know, here's where it gets real.
# Create the repository
repo_dict = {'name': my_repo_name,
'description': 'I made this repo with an API!',
'homepage': '',
'private': False,
'has_issues': True,
'has_wiki': True,
'has_downloads': False }
repo = None
# pop is really cool!
# it grabs the value matching the provided key and removes it from the dictionary
if repo_dict.get('name'):
repo = g.create_repo(repo_dict.pop('name'), **repo_dict)
if repo:
print('Repo created!')
Repo created!
# What did we make this time?
############## return value #####################
# GitHub.create_repo() returns an object of type:
# <class 'github3.repos.repo.Repository'>
# print(repo) displays: my_username/my_repo_name
#################################################
# So that's a Repository object.
if repo:
print('What can be done with a Repository object:')
print('=========================================')
public(repo)
What can be done with a Repository object: ========================================= add_collaborator archive archive_urlt asset assignees_urlt blob blobs_urlt branch branches_urlt clone_url comments_urlt commit commit_comment commits_urlt compare_commits compare_urlt contents contents_urlt contributors_url create_blob create_comment create_commit create_deployment create_file create_fork create_hook create_issue create_key create_label create_milestone create_pull create_pull_from_issue create_ref create_release create_status create_tag create_tree created_at default_branch delete delete_file delete_key delete_subscription description download_url edit etag events_url fork fork_count forks forks_count from_json full_name git_commit git_commits_urlt git_refs_urlt git_tags_urlt git_url has_downloads has_issues has_wiki homepage hook hooks_url html_url id is_assignee is_collaborator issue issue_comment_urlt issue_events_urlt issues_urlt iter_assignees iter_branches iter_code_frequency iter_collaborators iter_comments iter_comments_on_commit iter_commit_activity iter_commits iter_contributor_statistics iter_contributors iter_deployments iter_events iter_forks iter_hooks iter_issue_events iter_issues iter_keys iter_labels iter_languages iter_milestones iter_network_events iter_notifications iter_pages_builds iter_pulls iter_refs iter_releases iter_stargazers iter_statuses iter_subscribers iter_tags iter_teams key label labels_urlt language languages_url last_modified latest_pages_build mark_notifications master_branch merge merges_url milestone milestones_urlt mirror_url name notifications_urlt open_issues open_issues_count owner pages parent private pull_request pulls_urlt pushed_at ratelimit_remaining readme ref refresh release remove_collaborator set_subscription size source ssh_url stargazers stargazers_url statuses_urlt subscribers_url subscription subscription_url svn_url tag tags_url teams_url to_json tree trees_urlt update_file update_label updated_at watchers weekly_commit_count
# You can retrieve a repository if, for instance, you didn't just create one
r = g.repository(my_username, my_repo_name)
if r:
print('Repository {0} is saved as "r".\n'.format(r.name))
if r == repo:
print('This step was unnecessary; we already had our repository in a variable.')
Repository api-test is saved as "r". This step was unnecessary; we already had our repository in a variable.
Two files - a README (because good manners) and something called 'file.md.'
# Now we're going to add two files, README.md and file.md
# Here's the content we want to put inside the files (replace, if you want!)
contents = 'API Test\n======\n\nThis is the README for api-test. It was added via api.'
contents2 = 'This is the text of a file. It was added via api.'
# This is the message that will show up in the commit
commit_message = 'This was added via API, woo!'
create = r.create_file('README.md', commit_message, contents)
create2 = r.create_file('file.md', commit_message, contents2)
if create and create2:
print('The files were both created!')
The files were both created!
# And now what have we done?
############## return value ###############################################
# Repository.create_file() returns:
# {
# u'content': <Content [README.md]>,
# u'commit': <Commit [Your Name:00fca0f40d69166ab01bcd123a0569f463a4e335]>,
# u'ETag': '"5b78bfcf6cf345d6c950d462630850c6"',
# u'Last-Modified': u''
# }
###########################################################################
# So that's a dict object (yeah, plain old Python dicts, go figure)
# But notice it has a Content object in it and a Commit object in it
# We'll get to Content objects in a moment, but here's the skinny on a Commit object
if create:
print('What can be done with a Commit object:')
print('=====================================')
public(create['commit'])
What can be done with a Commit object: ===================================== author author_as_User committer committer_as_User etag from_json html_url last_modified message parents ratelimit_remaining refresh sha to_json tree
We'll be updating file.md.
# This is going to look like a digression, but it's relevant
# Let's look at the contents of the repository
all_the_files = r.contents('/')
print('You have the following files in your repository: ')
print(all_the_files)
# Get just one of the files, because we're going to update it
file_to_update = r.contents('file.md')
You have the following files in your repository: {u'file.md': <Content [file.md]>, u'README.md': <Content [README.md]>}
# And now?
############## return value ####################
# Repository.contents('filename') returns:
# <class 'github3.repos.contents.Contents'>
# Printing file_to_update displays:
# <Content [file.md]>
################################################
# So, that's a Content object
if file_to_update:
print('What can be done with a Content object:')
print('======================================')
public(file_to_update)
What can be done with a Content object: ====================================== content decoded delete encoding etag from_json git_url html_url last_modified links name path ratelimit_remaining refresh sha size submodule_git_url target to_json type update
# Here's the text of the update we want to make
update = 'This file was updated via the api.'
# Here's why we needed to grab that file; we needed its SHA
# A SHA is a checksum, and you could go read a lot about it...
# BUT if you don't care, it's basically what GitHub uses as the ID of a file
# or of a commit
# or of a tree
the_sha = file_to_update.sha
commit_message = 'Update made via API'
update_return = r.update_file('file.md', commit_message, update, the_sha)
# What have we got now?
############## return value ################################################
# Repository.update_file() returns:
# {
# u'content': <Content [file.md]>,
# u'commit': <Commit [Your Name:4e18f28f46188a9dd3bb7603ce8339cf57e5d026]>,
# u'ETag': '"dacf99cb0dde35b6210c1df729df2a4f"',
# u'Last-Modified': u''
# }
###########################################################################
# Another dict! With another Content and Commit in it!
# (It makes sense. Updating is a lot like creating.)
It isn't CRUD without the D. (Create Read Update and Delete)
r.create_file('deleteme.md', 'This file was added via api, but it is doomed.', contents)
delete_sha = r.contents('deleteme.md').sha
delete_return = r.delete_file('deleteme.md', 'this file was deleted via api', delete_sha)
if delete_return:
print('File \'deleteme.md\' was created and then deleted.')
File 'deleteme.md' was created and then deleted.
# What has happened?
############## return value ####################################
# Repository.delete_file() returns:
# <Commit [Your Name:539ef374984b0ae4809662ae6a198f214135f123]>
################################################################
# A commit object!
# And get the tree, because, tree
# You can get a tree with a SHA or with a branch name
# We didn't make any branches, explicitly, so we're on branch 'master'
t = r.tree('master')
# Finally?
############## return value ####################################
# Repository.tree() returns:
# <Tree [224bc857d84e2ab6743ae7ebf1b85562343e2d39]>
################################################################
if t:
print('What can be done with a Tree object:')
print('===================================')
public(t)
What can be done with a Tree object: =================================== etag from_json last_modified ratelimit_remaining recurse refresh sha to_json tree
# Wait wait wait. Tree has a thing that you can do called tree?!
# Let's explore.
if t:
print('\nHere is Tree.tree:')
print('=================')
print('It is type: {0}'.format(type(t.tree)))
print('\nOK, a list. Cool. ... A list of what?')
print('\nWhen you print the list, it looks like:')
print(t.tree)
print('\nHmm, the list contains objects of type Hash, neat.')
print('\nAnd what does it look like if we print a Hash?')
print(t.tree[0])
print('\nOh. The same.')
print('\n\nWhat can be done with a Hash object (one item in the Tree.tree list):')
print('====================================================================')
public(t.tree[0])
Here is Tree.tree: ================= It is type: <type 'list'> OK, a list. Cool. ... A list of what? When you print the list, it looks like: [<Hash [11e1377f4f31293d07a9a8dd3c7108c9e6f49cc1]>, <Hash [83bbf2c2a533d04d12fc25ff60d6d60fb604a182]>] Hmm, the list contains objects of type Hash, neat. And what does it look like if we print a Hash? <Hash [11e1377f4f31293d07a9a8dd3c7108c9e6f49cc1]> Oh. The same. What can be done with a Hash object (one item in the Tree.tree list): ==================================================================== etag from_json last_modified mode path sha size to_json type url