From d05a33420660a7375b057cf3c61404eb0373d3b2 Mon Sep 17 00:00:00 2001 From: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Date: Sat, 28 Mar 2026 04:47:54 +0000 Subject: [PATCH 1/2] :memo: reorg getting started --- docs/quickstart/index.md | 2 +- .../{ => getting-started}/authentication.md | 0 .../{ => getting-started}/configuration.md | 2 +- docs/usage/getting-started/reusing-client.md | 29 +++++++++++++++++ docs/usage/rest-api.md | 32 +------------------ mkdocs.yml | 6 ++-- 6 files changed, 36 insertions(+), 35 deletions(-) rename docs/usage/{ => getting-started}/authentication.md (100%) rename docs/usage/{ => getting-started}/configuration.md (98%) create mode 100644 docs/usage/getting-started/reusing-client.md diff --git a/docs/quickstart/index.md b/docs/quickstart/index.md index 8287179fd..dc30191fe 100644 --- a/docs/quickstart/index.md +++ b/docs/quickstart/index.md @@ -1,6 +1,6 @@ # Quick Start -Here are some common use cases to help you get started quickly. For more detailed usage, please refer to the [Usage](../usage/authentication.md) section. +Here are some common use cases to help you get started quickly. For more detailed usage, please refer to the [Usage](../usage/getting-started/authentication.md) section. !!! note diff --git a/docs/usage/authentication.md b/docs/usage/getting-started/authentication.md similarity index 100% rename from docs/usage/authentication.md rename to docs/usage/getting-started/authentication.md diff --git a/docs/usage/configuration.md b/docs/usage/getting-started/configuration.md similarity index 98% rename from docs/usage/configuration.md rename to docs/usage/getting-started/configuration.md index 3630c4647..d275b56ba 100644 --- a/docs/usage/configuration.md +++ b/docs/usage/getting-started/configuration.md @@ -177,7 +177,7 @@ Available built-in throttlers: ### `auto_retry` -The `auto_retry` option enables request retrying when rate limit exceeded and server error encountered. See [Auto Retry](./auto-retry.md) for more infomation. +The `auto_retry` option enables request retrying when rate limit exceeded and server error encountered. See [Auto Retry](../auto-retry.md) for more infomation. ### `rest_api_validate_body` diff --git a/docs/usage/getting-started/reusing-client.md b/docs/usage/getting-started/reusing-client.md new file mode 100644 index 000000000..13815768d --- /dev/null +++ b/docs/usage/getting-started/reusing-client.md @@ -0,0 +1,29 @@ +# Reusing Client + +You can make multiple requests with the same client instance in one context: + +=== "Sync" + + ```python hl_lines="4" + from githubkit import GitHub, Response + from githubkit.versions.latest.models import FullRepository + + with GitHub("") as github: + resp: Response[FullRepository] = github.rest.repos.get(owner="owner", repo="repo") + repo: FullRepository = resp.parsed_data + ``` + +=== "Async" + + ```python hl_lines="4" + from githubkit import GitHub, Response + from githubkit.versions.latest.models import FullRepository + + async with GitHub("") as github: + resp: Response[FullRepository] = await github.rest.repos.async_get(owner="owner", repo="repo") + repo: FullRepository = resp.parsed_data + ``` + +!!! warning + + Repeatedly creating new client instances may lead to memory leaks. We recommend reusing the same client instance within a single context to avoid this issue. diff --git a/docs/usage/rest-api.md b/docs/usage/rest-api.md index ef1ce3e62..f893d05f6 100644 --- a/docs/usage/rest-api.md +++ b/docs/usage/rest-api.md @@ -66,7 +66,7 @@ If you are calling an API that requires request body parameters, you can pass th !!! tip - By default, githubkit will validate the request body against the API schema. If you want to skip the validation, you can set the client config `rest_api_validate_body` to `False`. See [Configuration](./configuration.md#rest_api_validate_body) for more information. + By default, githubkit will validate the request body against the API schema. If you want to skip the validation, you can set the client config `rest_api_validate_body` to `False`. See [Configuration](./getting-started/configuration.md#rest_api_validate_body) for more information. Or you can pass the json request body as a dictionary: @@ -179,36 +179,6 @@ In some cases, you may need to pass additional headers to the API request. You c content = resp.text ``` -## Reusing Client - -You can make multiple requests with the same client instance in one context: - -=== "Sync" - - ```python hl_lines="4" - from githubkit import GitHub, Response - from githubkit.versions.latest.models import FullRepository - - with GitHub("") as github: - resp: Response[FullRepository] = github.rest.repos.get(owner="owner", repo="repo") - repo: FullRepository = resp.parsed_data - ``` - -=== "Async" - - ```python hl_lines="4" - from githubkit import GitHub, Response - from githubkit.versions.latest.models import FullRepository - - async with GitHub("") as github: - resp: Response[FullRepository] = await github.rest.repos.async_get(owner="owner", repo="repo") - repo: FullRepository = resp.parsed_data - ``` - -!!! warning - - Repeatedly creating new client instances may lead to memory leaks. We recommend reusing the same client instance within a single context to avoid this issue. - ## Data Validation As shown above, the response data is parsed and validated by accessing the `response.parsed_data` property. This ensures that the data type returned by the API is as expected and your code is safe to use it (with static type checking). But sometimes you may want to get the raw data returned by the API, such as when the schema is not correct. You can use the `response.text` property or `response.json()` method to get the raw data. The loaded json data is also typed but not validated. For example: diff --git a/mkdocs.yml b/mkdocs.yml index 831577cae..f9c0e748f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -131,8 +131,10 @@ nav: - OAuth APP Device Flow: quickstart/oauth-device-flow.md - GitHub APP: quickstart/github-app.md - Usage: - - Authentication: usage/authentication.md - - Configuration: usage/configuration.md + - Getting Started: + - Authentication: usage/getting-started/authentication.md + - Configuration: usage/getting-started/configuration.md + - Reusing Client: usage/getting-started/reusing-client.md - REST API: usage/rest-api.md - GraphQL: usage/graphql.md - Auto Retry: usage/auto-retry.md From a8327c3fe43ac37e8792558aa8d46ef7df22ba7d Mon Sep 17 00:00:00 2001 From: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Date: Sat, 28 Mar 2026 06:38:48 +0000 Subject: [PATCH 2/2] :memo: improve getting started docs --- docs/usage/getting-started/authentication.md | 193 +++++++++------- docs/usage/getting-started/configuration.md | 222 +++++++++++++------ docs/usage/getting-started/reusing-client.md | 25 ++- 3 files changed, 291 insertions(+), 149 deletions(-) diff --git a/docs/usage/getting-started/authentication.md b/docs/usage/getting-started/authentication.md index 8d282a5f0..d7498fda1 100644 --- a/docs/usage/getting-started/authentication.md +++ b/docs/usage/getting-started/authentication.md @@ -1,54 +1,70 @@ # Authentication -githubkit supports multiple authentication strategies to access the GitHub API. You can also switch between them easily when doing auth flow. +githubkit supports a variety of authentication strategies for the GitHub API. The following table summarizes all available strategies: + +| Strategy | Use Case | +| ------------------------------------------------------------------------ | ------------------------------ | +| [`UnauthAuthStrategy`](#without-authentication) | Public endpoints, quick tests | +| [`TokenAuthStrategy`](#token-authentication) | Personal Access Tokens (PAT) | +| [`AppAuthStrategy`](#github-app-authentication) | GitHub App (JWT) | +| [`AppInstallationAuthStrategy`](#github-app-installation-authentication) | GitHub App installation | +| [`OAuthAppAuthStrategy`](#oauth-app-authentication) | OAuth App (client credentials) | +| [`OAuthTokenAuthStrategy`](#oauth-user-token-authentication) | Stored user access tokens | +| [`OAuthWebAuthStrategy`](#oauth-web-flow-authentication) | OAuth web flow code exchange | +| [`OAuthDeviceAuthStrategy`](#oauth-device-flow-authentication) | OAuth device flow (CLI, IoT) | +| [`ActionAuthStrategy`](#github-action-authentication) | GitHub Actions workflows | + +All strategies are importable from the top-level `githubkit` package. ## Without Authentication -If you want to access GitHub API without authentication or make a temporary test, you can use `UnauthAuthStrategy`: +Access public GitHub API endpoints without credentials. Useful for quick tests, but subject to much lower [rate limits](https://docs.github.com/en/rest/rate-limit). ```python from githubkit import GitHub, UnauthAuthStrategy -# simply omit the auth parameter +# Simply omit the auth parameter github = GitHub() -# or, use UnauthAuthStrategy + +# Or explicitly use UnauthAuthStrategy github = GitHub(UnauthAuthStrategy()) ``` ## Token Authentication -You can authenticate to GitHub using a [Personal Access Token (PAT)](https://github.com/settings/personal-access-tokens/new). Replace `` with your token: +The simplest way to authenticate — pass a [Personal Access Token (PAT)](https://github.com/settings/personal-access-tokens/new) as a string. This works for both classic tokens and fine-grained PATs. ```python from githubkit import GitHub, TokenAuthStrategy -# simply pass the token as a string +# Shorthand: pass a token string directly github = GitHub("") -# or, use TokenAuthStrategy + +# Explicit: use TokenAuthStrategy github = GitHub(TokenAuthStrategy("")) ``` -## GitHub APP Authentication +!!! tip + + Store tokens in environment variables or a secrets manager — never hard-code them in source files. -If you are developing a GitHub App, you can authenticate using the GitHub App's private key and app ID. See [GitHub Docs - Authenticating as a GitHub App](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app) for more information. +## GitHub App Authentication -If you do not want to use OAuth features, you can omit the client ID and client secret. Replace ``, ``, ``, and `` with your app's credentials: +Authenticate **as a GitHub App** using a JSON Web Token (JWT) signed with the app's private key. This gives you access to app-level API endpoints (e.g., listing installations). See [GitHub Docs — Authenticating as a GitHub App](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app) for background. + +You can identify the app by **app ID** or **client ID** (GitHub supports both). The client ID and client secret are only required if you plan to use OAuth features (e.g., exchanging user tokens). ```python from githubkit import GitHub, AppAuthStrategy +# Using app ID (client ID and secret are optional) github = GitHub( AppAuthStrategy( "", "", "", "" ) ) -``` - -GitHub currently supports authentication using a GitHub App's private key and client ID. So, you could provide either the app ID or the client ID. - -```python -from githubkit import GitHub, AppAuthStrategy +# Using client ID instead of app ID github = GitHub( AppAuthStrategy( None, "", "", "" @@ -56,25 +72,23 @@ github = GitHub( ) ``` -## GitHub APP Installation Authentication +## GitHub App Installation Authentication -GitHub Ap installation allows the app to access resources owned by that installation, as long as the app was granted the necessary repository access and permissions. API requests made by an app installation are attributed to the app. For more information, see [GitHub Docs - Authenticating as an installation](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation). +Authenticate **as a specific installation** of your GitHub App. This grants access to the repositories and permissions that the organization or user has approved for that installation. API requests are attributed to the app. + +See [GitHub Docs — Authenticating as an installation](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation) for details. ```python from githubkit import GitHub, AppInstallationAuthStrategy +# Using app ID github = GitHub( AppInstallationAuthStrategy( "", "", installation_id, "", "", ) ) -``` - -App installation authentication also supports using the client ID instead of the app ID: - -```python -from githubkit import GitHub, AppInstallationAuthStrategy +# Using client ID instead of app ID github = GitHub( AppInstallationAuthStrategy( None, "", installation_id, "", "", @@ -82,9 +96,13 @@ github = GitHub( ) ``` -## OAuth APP Authentication +!!! tip + + You can also derive an installation client from a `GitHub` App instance using `with_auth` — see [Switching Auth Strategies](#switching-auth-strategies) below. -If you are developing an OAuth App, you can authenticate using the client ID and client secret. See [GitHub Docs - Authenticating with an OAuth App](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authenticating-to-the-rest-api-with-an-oauth-app) for more information. +## OAuth App Authentication + +Authenticate as an **OAuth App** using client credentials. This strategy uses [Basic authentication](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authenticating-to-the-rest-api-with-an-oauth-app) with the client ID and secret, which is required for certain endpoints (e.g., managing OAuth tokens). ```python from githubkit import GitHub, OAuthAppAuthStrategy @@ -94,9 +112,11 @@ github = GitHub(OAuthAppAuthStrategy("", "")) ## OAuth User Token Authentication -OAuth App (GitHub App) allows you to act on behalf of a user after the user authorized your app. You can authenticate using the user token. This auth strategy is usefull when you stored the user token in a database. +Act **on behalf of a user** using a previously obtained OAuth access token. This is the strategy to use when you have stored a user's token in your database and want to make API calls as that user. + +### Without token expiration -If you are developing an OAuth App or a GitHub App without user-to-server token expiration, you can authenticate using the user token directly: +For OAuth Apps or GitHub Apps **without** user-to-server token expiration enabled: ```python from githubkit import GitHub, OAuthTokenAuthStrategy @@ -108,7 +128,9 @@ github = GitHub( ) ``` -If you are developing a GitHub App with user-to-server token expiration, you need to provide the refresh token to keep the token up-to-date. In this case, you can omit the access token, but if you provide the access token, the access token expiration time is required: +### With token expiration (refresh tokens) + +For GitHub Apps **with** user-to-server token expiration enabled, provide the refresh token so githubkit can automatically renew expired access tokens. If you also supply the access token, you **must** include its expiration time: ```python from datetime import datetime @@ -119,48 +141,50 @@ github = GitHub( OAuthTokenAuthStrategy( "", "", - token="", # optional - expire_time=datetime(), # optional - refresh_token="", + token="", # optional if refresh_token is set + expire_time=datetime(), # required when token is provided + refresh_token="", # optional if token is set refresh_token_expire_time=datetime(), # optional ) ) ``` -If you want to refresh the access token immediately, you can normally call the `refresh` method: +### Manually refreshing the token + +You can force a token refresh at any time: ```python # sync -auth = github.auth.refresh(github) +github.auth.refresh(github) # async -auth = await github.auth.async_refresh(github) +await github.auth.async_refresh(github) ``` -This will update the access token and refresh token inplace. You can now store the new refresh token in `github.auth` to your database. +This updates the `token` and `refresh_token` attributes **in place** on the auth strategy object. After refreshing, persist the new values from `github.auth` to your database. ## OAuth Web Flow Authentication -GitHub OAuth web flow allows you to exchange the user access token with the web flow code. githubkit has built-in support for OAuth web flow token exchanging. See [GitHub Docs - Using the web application flow](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-web-application-flow-to-generate-a-user-access-token) for more information. +Exchange an OAuth **authorization code** (from the web application flow) for a user access token. See [GitHub Docs — Using the web application flow](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-web-application-flow-to-generate-a-user-access-token). ```python from githubkit import GitHub, OAuthWebAuthStrategy github = GitHub( - OAuthWebAuthStrategy( - "", "", "" - ) + OAuthWebAuthStrategy("", "", "") ) ``` -Note that this auth strategy is only for one-time use. You need to store the user access token and refresh token in your database for future use: +!!! warning + + This strategy is **one-time use** — the authorization code can only be exchanged once. After obtaining the token, persist it and switch to `OAuthTokenAuthStrategy` for subsequent requests. + +To exchange the code and retrieve the resulting token: ```python from githubkit import GitHub, OAuthWebAuthStrategy, OAuthTokenAuthStrategy github = GitHub( - OAuthWebAuthStrategy( - "", "", "" - ) + OAuthWebAuthStrategy("", "", "") ) # sync @@ -168,57 +192,55 @@ auth: OAuthTokenAuthStrategy = github.auth.exchange_token(github) # async auth: OAuthTokenAuthStrategy = await github.auth.async_exchange_token(github) +# Persist these values to your database access_token = auth.token refresh_token = auth.refresh_token ``` -See [Switch between AuthStrategy](#switch-between-authstrategy) for more detail about oauth flow. +See [Switching Auth Strategies](#switching-auth-strategies) for a complete example of web flow integration with `OAuthAppAuthStrategy`. ## OAuth Device Flow Authentication -OAuth device flow allows you to authenticate as a user without a web browser (e.g., cli tools, desktop apps). githubkit has built-in support for OAuth device flow. See [GitHub Docs - Using the device flow](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-device-flow-to-generate-a-user-access-token) for more information. +Authenticate a user on **input-constrained devices** (CLI tools, IoT, smart TVs) without a web browser. githubkit handles the polling loop automatically. See [GitHub Docs — Using the device flow](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-device-flow-to-generate-a-user-access-token). -Before you start the device flow, you need to create a callback function to display the user code to the user. The callback function will be called when the user code is generated, and githubkit will poll the server until the user successfully authenticated or code expired. +You must provide a **callback function** that displays the user code. githubkit calls this function when a code is generated, then polls the server until the user completes authentication or the code expires. ```python from githubkit import GitHub, OAuthDeviceAuthStrategy -# sync/async func for displaying user code to user -# the data dict is the generation response from the github server. -# see the link above for more fields in the response. def callback(data: dict): - print(data["user_code"]) + """Display the user code and verification URL to the user.""" + print(f"Open {data['verification_uri']} and enter code: {data['user_code']}") github = GitHub( - OAuthDeviceAuthStrategy( - "", callback - ) + OAuthDeviceAuthStrategy("", callback) ) ``` -Note that this auth strategy is only for one-time use too. You need to store the user access token and refresh token in your database for future use: +The callback receives the full device authorization response as a dict. Key fields can be found in the [GitHub Docs — Using the device flow](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-device-flow-to-generate-a-user-access-token). + +!!! warning + + This strategy is also **one-time use**. Exchange and persist the token for future requests: ```python from githubkit import GitHub, OAuthDeviceAuthStrategy, OAuthTokenAuthStrategy -github = GitHub( - OAuthDeviceAuthStrategy( - "", callback - ) -) +github = GitHub(OAuthDeviceAuthStrategy("", callback)) # sync auth: OAuthTokenAuthStrategy = github.auth.exchange_token(github) # async auth: OAuthTokenAuthStrategy = await github.auth.async_exchange_token(github) +# Persist these values access_token = auth.token refresh_token = auth.refresh_token ``` ## GitHub Action Authentication -githubkit provides a built-in auth strategy for GitHub Actions. You can use the `ActionAuthStrategy` to automatically authenticate to the GitHub API. +Authenticate automatically inside **GitHub Actions** workflows using the `GITHUB_TOKEN` provided by the runner. ```python from githubkit import GitHub, ActionAuthStrategy @@ -226,37 +248,42 @@ from githubkit import GitHub, ActionAuthStrategy github = GitHub(ActionAuthStrategy()) ``` -and add input or env to the action step: +Make sure the token is available to your step — pass it as an **input** or **environment variable**: ```yaml -- name: Some step use githubkit +- name: Run my script with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -- name: Some step use githubkit +# Or as an environment variable +- name: Run my script env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ``` -## Switch between AuthStrategy +## Switching Auth Strategies -You can change the auth strategy and get a new client simplely using `with_auth`. +The `with_auth` method creates a **new `GitHub` instance** with a different auth strategy while **sharing the same configuration** (base URL, timeout, cache, etc.). This is essential for OAuth flows where you start as an app and then act as a user. -Switch from GitHub App to a specific installation: +### GitHub App → Installation ```python from githubkit import GitHub, AppAuthStrategy github = GitHub(AppAuthStrategy("", "")) + +# Create a new client authenticated as a specific installation installation_github = github.with_auth( github.auth.as_installation(installation_id) ) ``` -Switch from GitHub App to an OAuth App: +### GitHub App → OAuth App + +Requires `client_id` and `client_secret` to be set on the `AppAuthStrategy`: ```python -from githubkit import GitHub, AppAuthStrategy, OAuthAppAuthStrategy +from githubkit import GitHub, AppAuthStrategy github = GitHub( AppAuthStrategy( @@ -267,59 +294,66 @@ github = GitHub( oauth_github = github.with_auth(github.auth.as_oauth_app()) ``` -Switch from OAuth App to a web user authorization (OAuth Web Flow): +### OAuth App → User (Web Flow) + +Exchange a web flow code for a user token and make requests as the user: ```python from githubkit import GitHub, OAuthAppAuthStrategy github = GitHub(OAuthAppAuthStrategy("", "")) + +# Create a client that acts as the user user_github = github.with_auth(github.auth.as_web_user("")) -# now you can act as the user +# Make a request as the user resp = user_github.rest.users.get_authenticated() user = resp.parsed_data -# you can get the user token after you maked a request as user +# Retrieve the tokens for persistence user_token = user_github.auth.token user_token_expire_time = user_github.auth.expire_time refresh_token = user_github.auth.refresh_token refresh_token_expire_time = user_github.auth.refresh_token_expire_time ``` -you can also get the user token directly without making a request (Switch from `OAuthWebAuthStrategy` to `OAuthTokenAuthStrategy`): +You can also exchange the code for a token **without making a request first**: ```python from githubkit import GitHub, OAuthAppAuthStrategy, OAuthTokenAuthStrategy github = GitHub(OAuthAppAuthStrategy("", "")) +# sync auth: OAuthTokenAuthStrategy = github.auth.as_web_user("").exchange_token(github) -# or asynchronously +# async auth: OAuthTokenAuthStrategy = await github.auth.as_web_user("").async_exchange_token(github) +# Persist the tokens user_token = auth.token user_token_expire_time = auth.expire_time refresh_token = auth.refresh_token refresh_token_expire_time = auth.refresh_token_expire_time +# Create a new client with the exchanged token user_github = github.with_auth(auth) ``` -Switch from `OAuthDeviceAuthStrategy` to `OAuthTokenAuthStrategy`: +### Device Flow → Token ```python -from githubkit import GitHub, OAuthDeviceAuthStrategy +from githubkit import GitHub, OAuthDeviceAuthStrategy, OAuthTokenAuthStrategy def callback(data: dict): print(data["user_code"]) user_github = GitHub(OAuthDeviceAuthStrategy("", callback)) -# now you can act as the user +# Option 1: Make a request first (triggers the device flow automatically) resp = user_github.rest.users.get_authenticated() user = resp.parsed_data -# you can get the user token after you maked a request as user +# Retrieve the tokens for persistence user_token = user_github.auth.token user_token_expire_time = user_github.auth.expire_time refresh_token = user_github.auth.refresh_token @@ -335,5 +369,6 @@ user_token_expire_time = auth.expire_time refresh_token = auth.refresh_token refresh_token_expire_time = auth.refresh_token_expire_time -user_github = github.with_auth(auth) +# Create a reusable client with the token +token_github = user_github.with_auth(auth) ``` diff --git a/docs/usage/getting-started/configuration.md b/docs/usage/getting-started/configuration.md index d275b56ba..9d0adc980 100644 --- a/docs/usage/getting-started/configuration.md +++ b/docs/usage/getting-started/configuration.md @@ -1,6 +1,6 @@ # Configuration -githubkit is highly configurable, you can change the default config by passing config options to `GitHub`: +githubkit is highly configurable. You can customize its behavior by passing keyword arguments directly to the `GitHub` constructor: ```python from githubkit import GitHub @@ -13,6 +13,10 @@ github = GitHub( follow_redirects=True, timeout=None, ssl_verify=True, + trust_env=True, + proxy=None, + transport=None, + async_transport=None, cache_strategy=None, http_cache=True, throttler=None, @@ -21,7 +25,7 @@ github = GitHub( ) ``` -Or, you can pass the config object directly (not recommended): +Alternatively, you can build a `Config` object and pass it via the `config` parameter. This is useful when you want to share the same configuration across multiple `GitHub` instances: ```python import httpx @@ -36,6 +40,10 @@ config = Config( follow_redirects=True, timeout=httpx.Timeout(None), ssl_verify=True, + trust_env=True, + proxy=None, + transport=None, + async_transport=None, cache_strategy=DEFAULT_CACHE_STRATEGY, http_cache=True, throttler=None, @@ -46,139 +54,217 @@ config = Config( github = GitHub(config=config) ``` +!!! note + + When using the `config` parameter, you **cannot** pass individual keyword arguments at the same time — they are mutually exclusive. + ## Options ### `base_url` -The `base_url` option is used to set the base URL of the GitHub API. If you are using GitHub Enterprise Server, you need to include the `/api/v3/` path in the base URL. +The base URL for all API requests. Defaults to `https://api.github.com/`. + +If you are using **GitHub Enterprise Server**, you must include the `/api/v3/` path suffix: + +```python +github = GitHub(base_url="https://github.example.com/api/v3/") +``` + +!!! note + + githubkit automatically appends a trailing slash (`/`) if one is missing. ### `accept_format`, `previews` -The `accept_format` and `previews` are used to set the default `Accept` header. By default, githubkit uses `application/vnd.github+json`. You can find more details in [GitHub API docs](https://docs.github.com/en/rest/overview/media-types). +These options control the `Accept` header sent with every request. By default, githubkit uses `application/vnd.github+json`. + +- **`accept_format`** — a media type suffix such as `"raw+json"` or `"html+json"`. The leading dot is optional; githubkit adds it automatically. See [GitHub API Media Types](https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api#media-types) for available formats. +- **`previews`** — a list of API preview feature names, e.g., `["starfox"]`. Do **not** include the `-preview` suffix — githubkit adds it for you. -The `accept_format` option could be set to `PARAM+json`, such as `raw+json`. +```python +# Request raw markdown content as JSON +github = GitHub(accept_format="raw+json") -The `previews` option could be set to a list of preview features, such as `["starfox"]`. You can find the preview feature names in the GitHub API docs. Note that you do not need to include the `-preview` suffix in the preview feature name. +# Enable an API preview feature +github = GitHub(previews=["starfox"]) +``` ### `user_agent` -The `user_agent` option is used to set the `User-Agent` header. By default, githubkit uses `GitHubKit/Python`. +Sets the `User-Agent` header. Defaults to `"GitHubKit/Python"`. ### `follow_redirects` -The `follow_redirects` option is used to enable or disable the HTTP redirect following feature. By default, githubkit follows the redirects. +Whether to automatically follow HTTP redirects (3xx responses). Enabled by default. ### `timeout` -The `timeout` option is used to set the request timeout. You can pass a float, `None` or `httpx.Timeout` to this field. By default, the requests will never timeout. See [Timeout](https://www.python-httpx.org/advanced/timeouts/) for more information. +The request timeout. Accepts a `float` (seconds), an `httpx.Timeout` object for fine-grained control, or `None` for no timeout (default). See [HTTPX Timeouts](https://www.python-httpx.org/advanced/timeouts/) for details. + +```python +import httpx + +# Simple: 10 second timeout for all operations +github = GitHub(timeout=10.0) + +# Fine-grained: different timeouts for connect vs. read +github = GitHub(timeout=httpx.Timeout(5.0, read=30.0)) +``` ### `ssl_verify` -The `ssl_verify` option is used to customize the SSL certificate verification. By default, githubkit enables the SSL certificate verification. If you want to disable the SSL certificate verification, you can set this option to `False`. Or you can provide a custom ssl context to this option. See [SSL](https://www.python-httpx.org/advanced/ssl/) for more information. +Controls SSL certificate verification. Defaults to `True`. + +- `True` — verify SSL certificates using the default CA bundle. +- `False` — **disable** SSL verification (not recommended for production). +- `ssl.SSLContext` — provide a custom SSL context for advanced use cases. + +See [HTTPX SSL](https://www.python-httpx.org/advanced/ssl/) for details. ### `trust_env` -If `trust_env` is set to `True`, githubkit (httpx) will look for the environment variables to configure the proxy and SSL certificate verification. By default, this option is set to `True`. If you want to disable this feature, you can set this option to `False`. +When `True` (default), githubkit (via HTTPX) reads environment variables such as `HTTP_PROXY`, `HTTPS_PROXY`, and `SSL_CERT_FILE` to configure proxies and SSL. Set to `False` to ignore these variables. ### `proxy` -If you want to set a proxy for client programmatically, you can pass a proxy URL to the `proxy` option. See [httpx's proxies documentation](https://www.python-httpx.org/advanced/proxies/) for more information. +Sets a proxy URL for all requests. Accepts a string, `httpx.URL`, or `httpx.Proxy` object. + +```python +github = GitHub(proxy="http://proxy.example.com:8080") +``` + +See [HTTPX Proxies](https://www.python-httpx.org/advanced/proxies/) for more details. + +!!! note + + If `trust_env` is `True` and no `proxy` is set, githubkit respects the `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` environment variables. ### `transport`, `async_transport` -These two options let you provide a custom [HTTPX transport](https://www.python-httpx.org/advanced/transports/) for the underlying HTTP client. +Provide custom [HTTPX transports](https://www.python-httpx.org/advanced/transports/) to replace the default networking layer. This is useful for: -They accept instances of the following types: +- **Unit testing** — inject `httpx.MockTransport` to stub API responses without making real HTTP calls. +- **Custom networking** — use alternative transport implementations (e.g., HTTP/3, Unix sockets). -- `httpx.BaseTransport` (sync transport) — pass via the `transport` option. -- `httpx.AsyncBaseTransport` (async transport) — pass via the `async_transport` option. +| Option | Type | Used for | +| ----------------- | -------------------------- | -------------- | +| `transport` | `httpx.BaseTransport` | Sync requests | +| `async_transport` | `httpx.AsyncBaseTransport` | Async requests | -When provided, githubkit will forward the transport to create the client. This is useful for: +```python +import httpx -- providing a custom network implementation; -- injecting test-only transports (for example `httpx.MockTransport`) to stub responses in unit tests; -- using alternative transports provided by HTTPX or third parties. +def mock_handler(request: httpx.Request) -> httpx.Response: + return httpx.Response(200, json={"login": "octocat"}) -Note that if you provide a custom transport, proxy environment variables will have no effect. If you set the option to `None`, HTTPX will create the default transport. +github = GitHub(transport=httpx.MockTransport(mock_handler)) +``` + +!!! warning + + When a custom transport is provided, proxy-related environment variables (`HTTP_PROXY`, etc.) have no effect. Set `transport` / `async_transport` to `None` (default) to use HTTPX's built-in transport. ### `cache_strategy` -The `cache_strategy` option defines how to cache the tokens or http responses. You can provide a githubkit built-in cache strategy or a custom one that implements the `BaseCacheStrategy` interface. By default, githubkit uses the `MemCacheStrategy` to cache the data in memory. +Controls how githubkit caches **tokens** (e.g., GitHub App installation tokens) and **HTTP responses**. The default is `MemCacheStrategy`, which stores data in process memory. -Available built-in cache strategies: +You can provide any built-in strategy or implement a custom one by subclassing `BaseCacheStrategy`. -- `MemCacheStrategy`: Cache the data in memory. +#### Built-in Cache Strategies - Normally, you do not need to specifically use this cache strategy. It is used by default. +**`MemCacheStrategy`** — In-memory cache (default) - ```python - from githubkit.cache import DEFAULT_CACHE_STRATEGY, MemCacheStrategy +No extra setup is needed. Each `MemCacheStrategy` instance maintains its own cache; the default instance is shared globally. - # Use the default cache strategy - github = GitHub(cache_strategy=DEFAULT_CACHE_STRATEGY) - # Or you can initialize another MemCacheStrategy instance - # this will create a new cache instance and not share the cache with the global one - github = GitHub(cache_strategy=MemCacheStrategy()) - ``` +```python +from githubkit import GitHub +from githubkit.cache import DEFAULT_CACHE_STRATEGY, MemCacheStrategy -- `RedisCacheStrategy`: Cache the data in Redis (Sync only). +# Use the global default (shared across all GitHub instances) +github = GitHub(cache_strategy=DEFAULT_CACHE_STRATEGY) - To cache the data in Redis (Sync only), you need to provide a redis client to the `RedisCacheStrategy`. For example: +# Or create an isolated cache instance +github = GitHub(cache_strategy=MemCacheStrategy()) +``` - ```python - from redis import Redis +**`RedisCacheStrategy`** — Redis cache (sync only) - github = GitHub( - cache_strategy=RedisCacheStrategy( - client=Redis(host="localhost", port=6379), prefix="githubkit:" - ) - ) - ``` +Stores tokens and HTTP responses in Redis. Requires the `redis` package. - The `prefix` option is used to set the key prefix in Redis. You should add a `:` at the end of the prefix if you want to use namespace like key format. Both `githubkit` and `hishel` will use the prefix to store the cache data. +```python +from redis import Redis +from githubkit import GitHub +from githubkit.cache import RedisCacheStrategy - Note that using this sync only cache strategy will cause the `GitHub` instance to be sync only. +github = GitHub( + cache_strategy=RedisCacheStrategy( + client=Redis(host="localhost", port=6379), + prefix="githubkit:", + ) +) +``` -- `AsyncRedisCacheStrategy`: Cache the data in Redis (Async only). +!!! warning - To cache the data in Redis (Async only), you need to provide an async redis client to the `AsyncRedisCacheStrategy`. For example: + Using `RedisCacheStrategy` restricts the `GitHub` instance to **sync-only** operations. - ```python - from redis.asyncio import Redis +**`AsyncRedisCacheStrategy`** — Redis cache (async only) - github = GitHub( - cache_strategy=AsyncRedisCacheStrategy( - client=Redis(host="localhost", port=6379), prefix="githubkit:" - ) - ) - ``` +The async counterpart of `RedisCacheStrategy`. Requires the `redis` package with async support (`redis.asyncio`). - The `prefix` option is used to set the key prefix in Redis. You should add a `:` at the end of the prefix if you want to use namespace like key format. Both `githubkit` and `hishel` will use the prefix to store the cache data. +```python +from redis.asyncio import Redis +from githubkit import GitHub +from githubkit.cache import AsyncRedisCacheStrategy - Note that using this async only cache strategy will cause the `GitHub` instance to be async only. +github = GitHub( + cache_strategy=AsyncRedisCacheStrategy( + client=Redis(host="localhost", port=6379), + prefix="githubkit:", + ) +) +``` + +!!! warning + + Using `AsyncRedisCacheStrategy` restricts the `GitHub` instance to **async-only** operations. + +!!! tip + + The `prefix` parameter adds a key namespace in Redis. Include a trailing colon (`:`) for readable key names (e.g., `"githubkit:"`). Both githubkit and [Hishel](https://hishel.com/) use this prefix. ### `http_cache` -The `http_cache` option enables the http caching feature powered by [Hishel](https://hishel.com/) for HTTPX. GitHub API limits the number of requests that you can make within a specific amount of time. This feature is useful to reduce the number of requests to GitHub API and avoid hitting the rate limit. +Enables HTTP response caching powered by [Hishel](https://hishel.com/). When enabled, githubkit respects standard HTTP caching headers (`ETag`, `Last-Modified`, `Cache-Control`) returned by the GitHub API. This reduces redundant API calls and helps you stay within [rate limits](https://docs.github.com/en/rest/rate-limit). -### `throttler` +Enabled by default (`True`). Set to `False` to disable. -The `throttler` option is used to control the request concurrency to avoid hitting the rate limit. You can provide a githubkit built-in throttler or a custom one that implements the `BaseThrottler` interface. By default, githubkit uses the `LocalThrottler` to control the request concurrency. +### `throttler` -Available built-in throttlers: +Controls request concurrency to prevent hitting GitHub's rate limits. By default, githubkit uses `LocalThrottler`, which limits concurrent requests within the current process or event loop. -- `LocalThrottler`: Control the request concurrency in the local process / event loop. +```python +from githubkit import GitHub +from githubkit.throttling import LocalThrottler - ```python - from githubkit.throttling import LocalThrottler +# Allow at most 100 concurrent requests +github = GitHub(throttler=LocalThrottler(100)) +``` - github = GitHub(throttler=LocalThrottler(100)) - ``` +You can implement a custom throttler by subclassing `BaseThrottler`. ### `auto_retry` -The `auto_retry` option enables request retrying when rate limit exceeded and server error encountered. See [Auto Retry](../auto-retry.md) for more infomation. +Enables automatic retrying of requests when a **rate limit is exceeded** (HTTP 403/429) or a **server error** (HTTP 5xx) is encountered. Enabled by default (`True`). + +- `True` — use the built-in retry strategy. +- `False` — disable auto-retry. +- `RetryDecisionFunc` — provide a custom callable for fine-grained control. + +See [Auto Retry](../auto-retry.md) for more information. ### `rest_api_validate_body` -The `rest_api_validate_body` option is used to enable or disable the rest API request body validation. By default, githubkit validates the input data against the GitHub API schema. If you do not want to validate the input data, you can set this option to `False`. +When `True` (default), githubkit validates REST API request bodies against the GitHub API schema **before** sending the request. This catches invalid payloads early with clear error messages. + +Set to `False` to skip validation, which can be useful if you need to send payloads that don't strictly match the schema (e.g., undocumented fields). diff --git a/docs/usage/getting-started/reusing-client.md b/docs/usage/getting-started/reusing-client.md index 13815768d..c67425c20 100644 --- a/docs/usage/getting-started/reusing-client.md +++ b/docs/usage/getting-started/reusing-client.md @@ -1,6 +1,10 @@ # Reusing Client -You can make multiple requests with the same client instance in one context: +githubkit manages an underlying [HTTPX](https://www.python-httpx.org/) client for making HTTP requests. You can use a **context manager** to ensure the HTTP client is properly created, reused, and closed when you're done. + +## Using the Context Manager + +Wrapping your `GitHub` instance in a `with` (sync) or `async with` (async) block creates a single HTTP client that is shared across all requests made inside that block, and automatically closed on exit: === "Sync" @@ -24,6 +28,23 @@ You can make multiple requests with the same client instance in one context: repo: FullRepository = resp.parsed_data ``` +!!! note + + A context manager cannot be entered twice. Attempting to nest `with github:` inside another `with github:` on the same instance will raise a `RuntimeError`. + +## Without the Context Manager + +You can also use `GitHub` without a context manager. In this case, githubkit creates a new HTTP client per request, which is convenient for one-off calls but less efficient for multiple requests: + +```python +from githubkit import GitHub + +github = GitHub("") +resp = github.rest.repos.get(owner="owner", repo="repo") +``` + + + !!! warning - Repeatedly creating new client instances may lead to memory leaks. We recommend reusing the same client instance within a single context to avoid this issue. + Repeatedly creating new HTTP clients may lead to **memory leaks**. We strongly recommend **using the context manager** for any workload that makes multiple API calls.