跳转到主要内容

最小化和有见地的GitHub API客户端

项目描述

Project Status: Active — The project has reached a stable, usable state and is being actively developed. CI Status https://codecov.io/gh/jwodder/ghreq/branch/master/graph/badge.svg https://img.shields.io/pypi/pyversions/ghreq.svg MIT License

GitHub | PyPI | 问题 | 变更日志

ghreq 是围绕 requests 的简单包装,针对与GitHub REST API一起使用进行了各种定制。显著特性包括

  • 在发出请求时,您只需指定API基本URL之后的URL部分。您甚至可以构建包含URL的对象来发出请求。

  • 默认情况下,所有请求方法都返回解码后的JSON。

  • 4xx和5xx响应自动引发错误,无需调用 raise_for_status()

  • 对于4xx和5xx响应引发的错误,错误信息中包含响应体。

  • 支持迭代分页结果

  • 接受(Accept)和 X-GitHub-Api-Version 头部会自动设置为推荐值。

  • 遵循 GitHub 对处理速率限制的建议,包括在更改请求之间等待以及响应速率限制错误时等待和重试

  • 自动在 5xx 错误上使用指数退避重试

安装

ghreq 需要 Python 3.8 或更高版本。只需使用 Python 3 的 pip 来安装它(您有 pip 吗?)

python3 -m pip install ghreq

示例

from ghreq import Client

with Client(token="your-api-token-here") as client:
    user = client.get("/user")
    print("I am user", user["login"])
    print()

    print("Here are my repositories:")
    for repo in client.paginate("/user/repos"):
        print(repo["full_name"])
    print()

    hello_world = client / "repos" / "octocat" / "Hello-World"
    details = hello_world.get()
    print(f"{details['full_name']} has been starred {details['stargazers_count']} times.")
    print("Here is the first page of its open issues & PRs:")
    for issue in (hello_world / "issues").get():
        print(f"#{issue['number']}: {issue['title']}")

API

Client

class Client:
    def __init__(
        *,
        token: str | None = None,
        api_url: str = DEFAULT_API_URL,
        session: requests.Session | None = None,
        set_headers: bool | None = None,
        user_agent: str | None = None,
        accept: str | None = DEFAULT_ACCEPT,
        api_version: str | None = DEFAULT_API_VERSION,
        mutation_delay: float = 1.0,
        retry_config: RetryConfig | None = None,
    )

用于与 GitHub REST API(或足够相似的 API)交互的 HTTP 客户端类。

构造函数参数

token

用于通过 API 认证的 GitHub 访问令牌(如果有的话)。

如果 set_headersFalse 或默认为 False,则忽略此参数。

api_url

请求方法传递的路径附加到其上的基础 URL。

session

用于发出请求的预配置 requests.Session 实例。如果没有提供会话,将实例化一个新的会话。

set_headers

是否为通过会话发出的请求设置各种头部。如果 set_headersNone,则默认为如果 sessionNone 则为 True,否则为 False

如果 set_headersTrue 或默认为 True,则在会话上设置以下请求头部

  • Accept(如果 acceptNone

  • Authorization(如果 tokenNone,设置为 "Bearer {token}"

  • User-Agent(如果 user_agentNone

  • X-GitHub-Api-Version(如果 api_versionNone

  • headers 中包含的任何其他附加头部

如果 set_headersFalse 或默认为 False,则 Client 不在会话上设置任何头部,并且忽略其他与头部相关的参数。

user_agent

要在请求头部中包含的用户代理字符串。如果未设置,则使用 requests 库的默认用户代理。

如果 set_headersFalse 或默认为 False,则忽略此参数。

accept

设置 Accept 头部的值。可以设置为 None 以完全不设置头部。

如果 set_headersFalse 或默认为 False,则忽略此参数。

api_version

设置 X-GitHub-Api-Version 头部的值。可以设置为 None 以完全不设置头部。

如果 set_headersFalse 或默认为 False,则忽略此参数。

headers

设置所有其他头部后,可选地将额外头部映射设置为会话的映射。

如果 set_headersFalse 或默认为 False,则忽略此参数。

mutation_delay

在发出 POSTPATCHPUTDELETE 请求时,如果自上次此类请求以来时间少于 mutation_delay 秒,则客户端将休眠足够长的时间以补足差异,然后再执行请求。

retry_config

请求重试机制配置。如果未设置,将使用所有默认属性的 RetryConfig 实例;请参见下面。

Client 实例可以用作上下文管理器,在这种情况下,它们会在退出时关闭内部的 requests.Session 实例(无论会话是否由用户提供)。

可以使用字符串(例如,client / "user")将 Client 实例“分割”,以获得一个 Endpoint 实例,该实例会向由 api_url 和“除数”组成的 URL 发送请求;请参见下面。

Client.request(
    method: str,
    path: str,
    json: Any = None,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    data: DataType = None,
    timeout: TimeoutType = None,
    allow_redirects: bool = True,
    stream: bool = False,
    raw: bool = False,
) -> Any

使用给定方法/动词执行 HTTP 请求。如果 pathhttp://https:// 开头,则将其用作请求的 URL。否则,path 将追加到构造函数中提供的 api_url 值,并在之间插入一个正斜杠(如果尚未存在)。因此,给定默认 api_urlclient,以下内容是等效的

client.request("GET", "user")

client.request("GET", "/user")

client.request("GET", "https://api.github.com/user")

如果请求成功,则将体解码为 JSON 并返回;如果体为空(可能除了空白字符),则返回 None。要使方法返回实际的 requests.Response 对象,请传递 raw=True(或 stream=True,这意味着它)。

剩余的参数与 requests 中的含义相同。

如果请求失败,它可能在尝试之间使用指数级增加的等待时间进行重试;请参见下面的 RetryConfig 文档。如果所有重试都未成功,则引发最终请求的异常。

如果请求失败,返回 4xx 或 5xx 响应,则引发 PrettyHTTPError

Client.get(
    path: str,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    timeout: TimeoutType = None,
    stream: bool = False,
    raw: bool = False,
) -> Any

执行 GET 请求。有关更多信息,请参见 request() 的文档。

Client.post(
    path: str,
    json: Any = None,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    data: DataType = None,
    timeout: TimeoutType = None,
    stream: bool = False,
    raw: bool = False,
) -> Any

执行 POST 请求。有关更多信息,请参见 request() 的文档。

Client.put(
    path: str,
    json: Any = None,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    data: DataType = None,
    timeout: TimeoutType = None,
    stream: bool = False,
    raw: bool = False,
) -> Any

执行 PUT 请求。有关更多信息,请参见 request() 的文档。

Client.patch(
    path: str,
    json: Any = None,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    data: DataType = None,
    timeout: TimeoutType = None,
    stream: bool = False,
    raw: bool = False,
) -> Any

执行 PATCH 请求。有关更多信息,请参见 request() 的文档。

Client.delete(
    path: str,
    json: Any = None,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    data: DataType = None,
    timeout: TimeoutType = None,
    stream: bool = False,
    raw: bool = False,
) -> Any

执行 DELETE 请求。有关更多信息,请参见 request() 的文档。

Client.paginate(
    path: str,
    *,
    params: ParamsType = None,
    headers: HeadersType = None,
    timeout: TimeoutType = None,
    raw: Literal[True, False] = False,
) -> Iterator

执行一系列分页的 GET 请求,并从每一页产生项目。只有 pathparams 参数用于初始请求;后续请求遵循每个响应的“next”条目中的 Link 标头。

响应体必须是 JSON 列表(在这种情况下,列表元素被产生)或 JSON 对象,其中恰好有一个字段是列表(在这种情况下,该列表的元素被产生);否则,发生错误。

如果 rawTrue,则返回迭代器将产生每一页作为 requests.Response 对象,而不是产生每一页的项目。

Client.close() -> None

关闭客户端的内部 requests.Session。之后不得再调用任何请求方法。

当使用 Client 作为上下文管理器时,此方法会在退出时自动调用。

Endpoint

class Endpoint:
    client: Client
    url: str

客户端实例和URL的组合。Endpoint具有与Client相同工作方式的request()get()post()put()patch()delete()paginate()方法,但Endpoint的方法不接收path参数;相反,它们会对存储的URL发起请求。这在您反复对同一URL及其路径发起请求时非常有用。

通过将左边的ClientEndpoint实例与右边的字符串使用/(除法)运算符组合来创建一个Endpoint实例。如果字符串以http://https://开头,它将直接用作结果的Endpoint的URL。否则,字符串将被附加到左边的对象的api_urlurl属性上,如果其中没有已存在的正斜杠,则插入一个正斜杠。因此,给定一个使用默认api_url构建的client,以下内容是等效的

client.get("repos/octocat/hello-world")

(client / "repos/octocat/hello-world").get()

(client / "repos" / "octocat" / "hello-world").get()

RetryConfig

class RetryConfig:
    def __init__(
        retries: int = 10,
        backoff_factor: float = 1.0,
        backoff_base: float = 1.25,
        backoff_jitter: float = 0.0
        backoff_max: float = 120.0,
        total_wait: float | None = 300.0,
        retry_statuses: Container[int] = range(500, 600),
    )

用于存储ghreq重试机制的配置的容器。如果(a)抛出不是ValueError(例如,连接或超时错误)的response.RequestException,或者(b)服务器响应状态码为403,并且存在Retry-After头信息或正文中包含字符串"rate limit",或者(c)服务器响应状态码列在retry_statuses中,则请求会被重试。

当请求被重试时,客户端会在连续请求之间休眠越来越长的时间,直到获得一个不可重试的响应,或者执行了retries重试尝试,或者从第一个请求开始的总时间超过了total_wait(如果已设置)。

第一次重试将在休眠backoff_factor * 0.1秒后发生,后续的重试将在休眠backoff_factor * backoff_base ** (retry_number - 1) + random.random() * backoff_jitter秒后发生,直到每个重试的最大休眠时间达到backoff_max。如果一个Retry-Afterx-ratelimit-reset头信息指示一个更长的休眠时间,则使用该值。如果此类头信息指示的持续时间会导致下一个重试尝试在total_wait被超过后发生,则提前停止重试。

PrettyHTTPError

class PrettyHTTPError(requests.HTTPError)

当收到状态码为4xx或5xx的响应时,请求方法会自动抛出的requests.HTTPError的子类。与父类不同,将PrettyHTTPError转换为字符串将生成包含响应体的字符串;如果体是JSON,则该JSON将以缩进格式打印。

常量

DEFAULT_ACCEPT = "application/vnd.github+json"

Client构造函数中accept参数的默认值

DEFAULT_API_URL = "https://api.github.com"

Client构造函数中api_url参数的默认值

DEFAULT_API_VERSION = "2022-11-28"

构造函数中 api_version 参数的默认值

实用函数

make_user_agent(name: str, version: str | None = None, url: str | None = None) -> str

使用给定的客户端名称、可选版本和可选 URL 创建用户代理字符串。字符串还将包括使用的 requests 库版本和 Python 的实现 & 版本。

get_github_api_url() -> str

如果 GITHUB_API_URL 环境变量设置为非空字符串,则返回该字符串;否则返回 DEFAULT_API_URL

项目详情


下载文件

下载您平台对应的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分布

ghreq-0.5.0.tar.gz (21.4 kB 查看哈希值)

上传时间 源代码

构建分布

ghreq-0.5.0-py3-none-any.whl (14.9 kB 查看哈希值)

上传时间 Python 3

支持者: