PyGithub Concepts: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(39 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 [[PyGithub_Programming_Model#Authentication_with_Username_and_Password|username and password]], [[PyGithub_Programming_Model#Authentication_with_Personal_Access_Token_.28PAT.29|personal access token (PAT)]] or [[PyGithub_Programming_Model#Authentication_with_JWT|JWT]], the base URL, the timeout, the user agent, the Retry strategy and the pool size.
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==
* [[PyGithub_Programming_Model#Authentication_with_Personal_Access_Token_.28PAT.29|Authentication with Personal Access Token (PAT)]]
Various authentication mechanism are invoked by appropriately configuring the main <code>Github</code> class.
* [[PyGithub_Programming_Model#Authentication_with_Username_and_Password|Authentication with Username and Password]]
===Authentication with Personal Access Token (PAT)===
* [[PyGithub_Programming_Model#Authentication_with_JWT|Authentication with JWT]]
<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==
If the Github server requires the client to authenticate, and the client does not, or uses a self-signed certificate, an invocation fails with:
<syntaxhighlight lang='text'>
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>
==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 &#124; 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 &#124; 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

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 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 PaginatedLists. 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 AuthenticatedUsers and NamedUsers.

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

https://pygithub.readthedocs.io/en/latest/github_objects/AuthenticatedUser.html
GitHub Concepts | Authenticated User

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

https://pygithub.readthedocs.io/en/latest/examples/Repository.html

Repository Attributes

full_name

Get a Repository

github = Github(...)
repo = github.get_repo('some-owner/some-repo')

Issue

https://pygithub.readthedocs.io/en/latest/examples/Issue.html
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:

GitHub Concepts | PR States

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>.

See: https://docs.github.com/en/rest/reference/pulls