/githubkit

The modern, all-batteries-included GitHub SDK for Python, including rest api, graphql, webhooks, like octokit!

Primary LanguagePythonMIT LicenseMIT

githubkit

license pypi python black pyright ruff pre-commit

✨ The modern, all-batteries-included GitHub SDK for Python ✨

✨ Support both sync and async calls, fully typed

✨ Always up to date, like octokit ✨

Installation

pip install githubkit
# or, use poetry
poetry add githubkit
# or, use pdm
pdm add githubkit

if you want to auth as github app, extra dependencies are required:

pip install githubkit[auth-app]
# or, use poetry
poetry add githubkit[auth-app]
# or, use pdm
pdm add githubkit[auth-app]

if you want to mix sync and async calls in oauth device callback, extra dependencies are required:

pip install githubkit[auth-oauth-device]
# or, use poetry
poetry add githubkit[auth-oauth-device]
# or, use pdm
pdm add githubkit[auth-oauth-device]

Usage

Authentication

Initialize a github client with no authentication:

from githubkit import GitHub, UnauthAuthStrategy

github = GitHub()
# or, use UnauthAuthStrategy
github = GitHub(UnauthAuthStrategy())

or using PAT (Token):

from githubkit import GitHub, TokenAuthStrategy

github = GitHub("<your_token_here>")
# or, use TokenAuthStrategy
github = GitHub(TokenAuthStrategy("<your_token_here>"))

or using GitHub APP authentication:

from githubkit import GitHub, AppAuthStrategy

github = GitHub(
    AppAuthStrategy(
        "<app_id>", "<private_key>", "<optional_client_id>", "<optional_client_secret>"
    )
)

or using GitHub APP Installation authentication:

from githubkit import GitHub, AppInstallationAuthStrategy

github = GitHub(
    AppInstallationAuthStrategy(
        "<app_id>", "<private_key>", installation_id, "<optional_client_id>", "<optional_client_secret>",
    )
)

or using OAuth APP authentication:

from githubkit import GitHub, OAuthAppAuthStrategy

github = GitHub(OAuthAppAuthStrategy("<client_id_here>", "<client_secret_here>"))

or using GitHub APP / OAuth APP web flow authentication:

from githubkit import GitHub, OAuthWebAuthStrategy

github = GitHub(
    OAuthWebAuthStrategy(
        "<client_id_here>", "<client_secret_here>", "<web_flow_exchange_code_here>"
    )
)

or using GitHub Action authentication:

from githubkit import GitHub, ActionAuthStrategy

github = GitHub(ActionAuthStrategy())

Calling Rest API

APIs are fully typed. Typing in the following examples is just for reference only.

Simple sync call:

from githubkit import Response
from githubkit.rest import FullRepository

resp: Response[FullRepository] = github.rest.repos.get(owner="owner", repo="repo")
repo: FullRepository = resp.parsed_data

Simple async call:

from githubkit import Response
from githubkit.rest import FullRepository

resp: Response[FullRepository] = await github.rest.repos.async_get(owner="owner", repo="repo")
repo: FullRepository = resp.parsed_data

Call API with context (reusing client):

from githubkit import Response
from githubkit.rest import FullRepository

with GitHub("<your_token_here>") as github:
    resp: Response[FullRepository] = github.rest.repos.get(owner="owner", repo="repo")
    repo: FullRepository = resp.parsed_data
from githubkit import Response
from githubkit.rest import FullRepository

async with GitHub("<your_token_here>") as github:
    resp: Response[FullRepository] = await github.rest.repos.async_get(owner="owner", repo="repo")
    repo: FullRepository = resp.parsed_data

Pagination

Pagination type checking is also supported:

Typing is tested with Pylance (Pyright).

from githubkit.rest import Issue

for issue in github.paginate(
    github.rest.issues.list_for_repo, owner="owner", repo="repo", state="open"
):
    issue: Issue
    print(issue.number)
from githubkit.rest import Issue

async for issue in github.paginate(
    github.rest.issues.async_list_for_repo, owner="owner", repo="repo", state="open"
):
    issue: Issue
    print(issue.number)

complex pagination with custom map function (some api returns data in a nested field):

async for accessible_repo in github.paginate(
    github.rest.apps.async_list_installation_repos_for_authenticated_user,
    map_func=lambda r: r.parsed_data.repositories,
    installation_id=1,
):
    accessible_repo: Repository
    print(accessible_repo.full_name)

Calling GraphQL API

Simple sync call:

data: Dict[str, Any] = github.graphql(query, variables={"foo": "bar"})

Simple async call:

data: Dict[str, Any] = github.async_graphql(query, variables={"foo": "bar"})

Webhook Verification

Simple webhook payload verification:

from githubkit.webhooks import verify

valid: bool = verify(secret, request.body, request.headers["X-Hub-Signature-256"])

Sign the webhook payload manually:

from githubkit.webhooks import sign

signature: str = sign(secret, payload, method="sha256")

Webhook Parsing

Parse the payload with event name:

from githubkit.webhooks import parse, WebhookEvent

event: WebhookEvent = parse(request.headers["X-GitHub-Event"], request.body)

Parse the payload without event name (may cost longer time):

from githubkit.webhooks import parse_without_name, WebhookEvent

event: WebhookEvent = parse_without_name(request.body)

Parse dict like payload:

from githubkit.webhooks import parse_obj, parse_obj_without_name, WebhookEvent

event: WebhookEvent = parse_obj(request.headers["X-GitHub-Event"], request.json())
event: WebhookEvent = parse_obj_without_name(request.json())

Switch between AuthStrategy

You can change the auth strategy and get a new client simplely using with_auth.

Change from AppAuthStrategy to AppInstallationAuthStrategy:

from githubkit import GitHub, AppAuthStrategy

github = GitHub(AppAuthStrategy("<app_id>", "<private_key>"))
installation_github = github.with_auth(
    github.auth.as_installation(installation_id)
)

Change from OAuthAppAuthStrategy to OAuthWebAuthStrategy:

from githubkit import GitHub, OAuthAppAuthStrategy

github = GitHub(OAuthAppAuthStrategy("<client_id>", "<client_secret>"))
user_github = github.with_auth(github.auth.as_web_user("<code>"))

Development

Open in Codespaces (Dev Container):

Open in GitHub Codespaces

Generate latest models and apis:

python -m codegen && isort . && black .