PyGithub Concepts: Difference between revisions
(38 intermediate revisions by the same user not shown) | |||
Line 4: | Line 4: | ||
=<tt>Github</tt>= | =<tt>Github</tt>= | ||
{{External|https://pygithub.readthedocs.io/en/latest/github.html}} | {{External|https://pygithub.readthedocs.io/en/latest/github.html}} | ||
The main class to instantiate to access the GitHub API. It is used to configure authentication, via [[ | The main class to instantiate to access the GitHub API. It is used to configure authentication, via [[#Authentication_with_Username_and_Password|username and password]], [[#Authentication_with_Personal_Access_Token_.28PAT.29|personal access token (PAT)]] or [[#Authentication_with_JWT|JWT]], the [[#Base_URL|base URL]], the timeout, the user agent, the [[#The_Retry_Strategy|Retry strategy]], the [[#Pagination|page size]] and the pool size. | ||
==Base URL== | |||
The <code>base_url</code> consists of the host URL and API endpoint: | |||
<syntaxhighlight lang='py'> | |||
from github import Github | |||
host_url = 'https://github.com' | |||
api_endpoint = 'api/v3' | |||
base_url = f'{host_url}/{api_endpoint}' | |||
github = Github(base_url=base_url,, ...) | |||
</syntaxhighlight> | |||
==Authentication== | ==Authentication== | ||
Various authentication mechanism are invoked by appropriately configuring the main <code>Github</code> class. | |||
===Authentication with Personal Access Token (PAT)=== | |||
<syntaxhighlight lang='py'> | |||
from github import Github | |||
github_pat = os.environ.get('GITHUB_PAT') | |||
if not github_pat: | |||
raise ValueError("'GITHUB_PAT' not found in environment") | |||
github = Github(base_url='https://github.com/api/v3', login_or_token=github_pat) | |||
</syntaxhighlight> | |||
===Authentication with Username and Password=== | |||
<syntaxhighlight lang='py'> | |||
github = Github(base_url='https://github.com/api/v3', login_or_token='someusername', password='somepassword') | |||
</syntaxhighlight> | |||
Note that the invocation '''does not''' fail if the username or the password is invalid. Subsequent calls are made as unauthenticated user. | |||
===Authentication with JWT=== | |||
==Authenticated SSL Client== | ==Authenticated SSL Client== | ||
If the Github server requires the client to authenticate, and the client does not, or uses a self-signed certificate, an invocation fails with: | If the Github server requires the client to authenticate, and the client does not, or uses a self-signed certificate, an invocation fails with: | ||
Line 14: | Line 41: | ||
requests.exceptions.SSLError: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /api/v3/user/repos?per_page=100 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)'))) | requests.exceptions.SSLError: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /api/v3/user/repos?per_page=100 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)'))) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==The Retry Strategy== | |||
<syntaxhighlight lang='py'> | |||
status_forcelist = [403, 500, 502, 504] # retry 403s, 5XX from GitHub | |||
retry = Retry(total=10, backoff_factor=0.2, raise_on_status=True, status_forcelist=status_forcelist) | |||
github = Github(base_url='...', retry=retry, ...) | |||
</syntaxhighlight> | |||
==Pagination== | |||
Responses that potentially may include a large number of elements are returned as <code>[[#PaginatedList|PaginatedList]]</code>s. The page size is controlled by the value of the <code>per_page</code> <code>Github</code> constructor parameter. If not specified <font color=darkkhaki>the default value is ?</font> | |||
===<tt>PaginatedList</tt>=== | |||
The total number of elements can be obtained with <code>paginated_list.totalCount</code>. | |||
=User= | |||
There are <code>[[#AuthenticatedUser|AuthenticatedUser]]</code>s and <code>[[#NamedUser|NamedUser]]</code>s. | |||
All users <font color=darkkhaki>from where? entire site? organization?</font> are returned with <code>Github#get_users()</code>. | |||
The current user, even if the authentication failed, is returned as an <code>AuthenticatedUser</code> instance, in response to <code>Github#get_user()</code>. However, the instance is lazy instantiated, so the attempt to get a specific attribute will end up in invoking <code>_requester.requestJsonAndCheck(...)</code>, which will cause a 403 "API rate limit exceeded [...] Authenticated requests get a higher rate limit." | |||
==<tt>AuthenticatedUser</tt>== | |||
{{External|https://pygithub.readthedocs.io/en/latest/github_objects/AuthenticatedUser.html}} | |||
{{Internal|GitHub_Concepts#Authenticated_User|GitHub Concepts | Authenticated User}} | |||
The invocation on any of the following attributes on an <code>AuthenticatedUser</code> instance corresponding to the "current user" is equivalent with: | |||
<syntaxhighlight lang='bash'> | |||
curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_PAT}" -H "X-GitHub-Api-Version: 2022-11-28" https://github.com/api/v3/user | |||
</syntaxhighlight> | |||
To get a specific user: | |||
<syntaxhighlight lang='bash'> | |||
curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_PAT}" -H "X-GitHub-Api-Version: 2022-11-28" https://github.com/api/v3/users/<user-login> | |||
</syntaxhighlight> | |||
===<tt>login</tt>=== | |||
===<tt>id</tt>=== | |||
===<tt>name</tt>=== | |||
===<tt>type</tt>=== | |||
<code>User</code>. | |||
===<tt>url</tt>=== | |||
===<tt>updated_at</tt>=== | |||
===<tt>node_id</tt>=== | |||
===<tt>organizations_url</tt>=== | |||
===<tt>repos_url</tt>=== | |||
==<tt>NamedUser</tt>== | |||
=Repository= | |||
{{External|https://pygithub.readthedocs.io/en/latest/examples/Repository.html}} | |||
==Repository Attributes== | |||
===<code>full_name</code>=== | |||
==Get a Repository== | |||
<syntaxhighlight lang='py'> | |||
github = Github(...) | |||
repo = github.get_repo('some-owner/some-repo') | |||
</syntaxhighlight> | |||
=Issue= | |||
{{External|https://pygithub.readthedocs.io/en/latest/examples/Issue.html}} | |||
<syntaxhighlight lang='py'> | |||
repo = ... | |||
issues = repo.get_issues(state=state, milestone=milestone) | |||
</syntaxhighlight> | |||
=Milestone= | |||
<syntaxhighlight lang='py'> | |||
repo = ... | |||
milestones = repo.get_milestones() | |||
</syntaxhighlight> | |||
=Pull Request (PR)= | |||
==Get Multiple PRs from a Repository== | |||
Calls <code>GET /repos/<owner>/<repo>/pulls</code>. See: https://docs.github.com/en/rest/reference/pulls for reference. | |||
Returns a [[#PaginatedList|paginated list]] of <code>PullRequest</code> instances. | |||
<syntaxhighlight lang='py'> | |||
repository = ... | |||
paginated_list = repository.get_pulls( | |||
state='open'|'closed'|'all', | |||
base='...', | |||
sort='...', | |||
direction='...' | |||
per_page=30 | |||
) | |||
</syntaxhighlight> | |||
===<tt>state</tt>=== | |||
If the state is invalid (not one of 'open', 'closed' or 'all'), the method returns a result corresponding to 'open'. For more details, see: {{Internal|GitHub_Concepts#PR_States|GitHub Concepts | PR States}} | |||
===<tt>base</tt>=== | |||
The base branch name. If no such branch, the method returns an empty list. | |||
===<tt>sort</tt>=== | |||
A string indicating what to sort results by: | |||
* 'popularity': sort by the number of comments. | |||
* 'created': (default) | |||
* 'updated': | |||
* 'long-running': will sort by date created and will limit the results to pull requests that have been open for more than a month and have had activity within the past month. | |||
===<tt>direction</tt>=== | |||
The direction of the sort. Default: 'desc' when sort is created or sort is not specified, otherwise 'asc'. | |||
===<tt>per_page</tt>=== | |||
Number of results per page, as integer. Default 30, max 100. | |||
===<tt>page</tt>=== | |||
Page number of the results to fetch, default 1. | |||
==Get One PR from a Repository== | |||
Calls <code>GET /repos/<owner>/<repo>/pulls/<pr-number></code>. | |||
See: https://docs.github.com/en/rest/reference/pulls |
Latest revision as of 21:46, 18 May 2023
Internal
Github
The main class to instantiate to access the GitHub API. It is used to configure authentication, via username and password, personal access token (PAT) or JWT, the base URL, the timeout, the user agent, the Retry strategy, the page size and the pool size.
Base URL
The base_url
consists of the host URL and API endpoint:
from github import Github
host_url = 'https://github.com'
api_endpoint = 'api/v3'
base_url = f'{host_url}/{api_endpoint}'
github = Github(base_url=base_url,, ...)
Authentication
Various authentication mechanism are invoked by appropriately configuring the main Github
class.
Authentication with Personal Access Token (PAT)
from github import Github
github_pat = os.environ.get('GITHUB_PAT')
if not github_pat:
raise ValueError("'GITHUB_PAT' not found in environment")
github = Github(base_url='https://github.com/api/v3', login_or_token=github_pat)
Authentication with Username and Password
github = Github(base_url='https://github.com/api/v3', login_or_token='someusername', password='somepassword')
Note that the invocation does not fail if the username or the password is invalid. Subsequent calls are made as unauthenticated user.
Authentication with JWT
Authenticated SSL Client
If the Github server requires the client to authenticate, and the client does not, or uses a self-signed certificate, an invocation fails with:
requests.exceptions.SSLError: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /api/v3/user/repos?per_page=100 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)')))
The Retry Strategy
status_forcelist = [403, 500, 502, 504] # retry 403s, 5XX from GitHub
retry = Retry(total=10, backoff_factor=0.2, raise_on_status=True, status_forcelist=status_forcelist)
github = Github(base_url='...', retry=retry, ...)
Pagination
Responses that potentially may include a large number of elements are returned as PaginatedList
s. The page size is controlled by the value of the per_page
Github
constructor parameter. If not specified the default value is ?
PaginatedList
The total number of elements can be obtained with paginated_list.totalCount
.
User
There are AuthenticatedUser
s and NamedUser
s.
All users from where? entire site? organization? are returned with Github#get_users()
.
The current user, even if the authentication failed, is returned as an AuthenticatedUser
instance, in response to Github#get_user()
. However, the instance is lazy instantiated, so the attempt to get a specific attribute will end up in invoking _requester.requestJsonAndCheck(...)
, which will cause a 403 "API rate limit exceeded [...] Authenticated requests get a higher rate limit."
AuthenticatedUser
The invocation on any of the following attributes on an AuthenticatedUser
instance corresponding to the "current user" is equivalent with:
curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_PAT}" -H "X-GitHub-Api-Version: 2022-11-28" https://github.com/api/v3/user
To get a specific user:
curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_PAT}" -H "X-GitHub-Api-Version: 2022-11-28" https://github.com/api/v3/users/<user-login>
login
id
name
type
User
.
url
updated_at
node_id
organizations_url
repos_url
NamedUser
Repository
Repository Attributes
full_name
Get a Repository
github = Github(...)
repo = github.get_repo('some-owner/some-repo')
Issue
repo = ...
issues = repo.get_issues(state=state, milestone=milestone)
Milestone
repo = ...
milestones = repo.get_milestones()
Pull Request (PR)
Get Multiple PRs from a Repository
Calls GET /repos/<owner>/<repo>/pulls
. See: https://docs.github.com/en/rest/reference/pulls for reference.
Returns a paginated list of PullRequest
instances.
repository = ...
paginated_list = repository.get_pulls(
state='open'|'closed'|'all',
base='...',
sort='...',
direction='...'
per_page=30
)
state
If the state is invalid (not one of 'open', 'closed' or 'all'), the method returns a result corresponding to 'open'. For more details, see:
base
The base branch name. If no such branch, the method returns an empty list.
sort
A string indicating what to sort results by:
- 'popularity': sort by the number of comments.
- 'created': (default)
- 'updated':
- 'long-running': will sort by date created and will limit the results to pull requests that have been open for more than a month and have had activity within the past month.
direction
The direction of the sort. Default: 'desc' when sort is created or sort is not specified, otherwise 'asc'.
per_page
Number of results per page, as integer. Default 30, max 100.
page
Page number of the results to fetch, default 1.
Get One PR from a Repository
Calls GET /repos/<owner>/<repo>/pulls/<pr-number>
.