An async GitHub API library for Python

brettcannon, updated 🕥 2022-10-04 22:00:59

gidgethub

An asynchronous GitHub API <https://docs.github.com/>_ library.

Development status

.. image:: https://github.com/brettcannon/gidgethub/workflows/CI/badge.svg?event=push :target: https://github.com/brettcannon/gidgethub/actions

.. image:: https://codecov.io/gh/brettcannon/gidgethub/branch/master/graph/badge.svg :target: https://codecov.io/gh/brettcannon/gidgethub

.. image:: https://readthedocs.org/projects/gidgethub/badge/?version=latest :target: http://gidgethub.readthedocs.io/en/latest/ :alt: Documentation Status

Installation

Gidgethub is available on PyPI <https://pypi.org/project/gidgethub/>_. ::

python3 -m pip install gidgethub

Gidgethub requires Python version 3.7 and up.

Goals

The key goal is to provide a base library for the GitHub API <https://docs.github.com/> which performs no I/O of its own (a sans-I/O <https://sans-io.readthedocs.io/> library). This allows users to choose whatever HTTP library they prefer while parceling out GitHub-specific details to this library. This base library is then built upon to provide an abstract base class to a cleaner API to work with. Finally, implementations of the abstract base class are provided for asynchronous HTTP libraries for immediate usage.

Alternative libraries

If you think you want a different approach to the GitHub API, GitHub maintains a list of libraries <https://docs.github.com/en/[email protected]/rest/overview/libraries>_.

Aside: what's with the name?

I couldn't think of a good name that was somehow a play on "GitHub" or somehow tied into Monty Python <http://www.montypython.com/>. And so I decided to play off of GitHub's octocat <https://octodex.github.com/> mascot and use my own cat's name, Gidget, in some way. Since "Gidget" somewhat sounds like "git", I decided to go with "gidgethub".

Changelog

See the documentation for the full changelog <https://gidgethub.readthedocs.io/en/latest/changelog.html>_.

Issues

Use `ParamSpec` on the `Router.register` decorator

opened on 2023-03-30 14:10:03 by pradyunsg

https://peps.python.org/pep-0612/

This would enable rich type checking when calling the specific webhook handlers.

```py @ROUTER.register("installation") async def sync_installed_repos(event: Event, *, different_data: str) -> None: different_handler(event, different_data=computed_from(my_custom_data))

@ROUTER.register("installation_repositories") def different_handler(event: Event, *, my_custom_data: str): different_data = computed_from(my_custom_data) sync_installed_repos(event, different_data=different_data) ```

This would involve adding a dependency on typing_extensions or having a conditional definition of AsyncCallback.

Recover status code after request

opened on 2022-10-26 11:03:26 by GuillemBarroso

Hi!

I am using gidgethub to create a bot within a GitHub App. I am struggling when checking whether a user is member of a certain organization, see GitHub documentation for this call.

From what I understood, gh.getitem only returns the body of the request. However, the call mentioned above only returns a status code as a response (either 204, 302 or 404). Thus, I am not sure how to recover this status code after using await gh.getitem(url, oauth_token=oauth_token).

Please, let me know if I am misunderstanding something. Thanks!

Replace use of `requests` in examples with `httpx`

opened on 2022-03-09 23:55:56 by brettcannon

E.g. https://gidgethub.readthedocs.io/en/latest/sansio.html#requests .

gidgethub.InvalidField: Validation Failed for 'q'

opened on 2021-08-23 20:46:52 by mpushki

Try to use /search/issues. my query works good on guthub page. But I get problem in getitem await gh.getitem(f"/search/issues?q=type:pr") await gh.getitem(f"/search/issues?q=is::pr") Get error - gidgethub.InvalidField: Validation Failed for 'q' But await gh.getitem(f"/search/issues?q=is:merged+type:pr") works Also my repo contains dots. And await gh.getitem(f"/search/issues?q=repo:{name_with_dots}") does not work. My last params is date: merged:>YYYY-MM-DD - it does not work too in gh.getitem

It looks so strange. Could you please help me with this problem?

Unable to catch (release API) errors without reconnection

opened on 2021-07-28 11:32:35 by phlax

im using gidgethub to push releases/artefacts.

if an artefact exists already it throws a gidgethub.InvalidField: Validation Failed for 'name'

if i catch the error, i have to reconnect (ie delete/create new) the session/GitHubAPI objects

im wondering if there is either a way to catch errors without the connection hosing, or a good/canonical way to reconnect if it does

Docs should describe GitHub app authentication flow

opened on 2021-04-05 19:34:57 by tgamblin

This might be a duplicate of #107, but I thought I'd post anyway, since gidgethub has been mostly intuitive to me, except for app authentication. I did see this comment, so, apologies in advance if this just isn't something you want to do.

Scenario: I'm making a bot for Spack, to ping maintainers about their packages. A user followed GitHub's tutorial and made a prototype bot in Ruby, but we're a Python project, and I wanted to make it easy for contributors to hack the bot in Python. I started with octomachinery, as it eliminates a fair bit of the boilerplate, but it is surprisingly (for a Python project) GPL3, so we cannot use it in Spack. I figured I'd just implement the auth myself since octomachinery uses gidgethub for much of the heavy lifting anyway.

Long story short, it took me a while to understand how to put everything in the GitHub guide together on the Python side. I had to:

  1. Figure out that most of what I wanted was in gidgethub.apps
  2. Map those steps back to GitHub's guide
  3. Verify that everything the GitHub examples do is also done in GidgetHub (e.g., that webhooks were verified as part of creating an Event).

I could not find resources that told me I had to make a JWT token and use that to get an installation access token based on each reqeust. @Mariatta's excellent bot tutorial seems to get OAuth tokens directly from the environment, instead of doing the JWT -> installation access token dance, as do the Bedevere and Miss Islington examples.

Maybe I am missing something about those, but it seems like the docs should have an example of how to use the GitHub app authentication flow, as I think most new bots will want to do this.

Anyway, thanks for Gidgethub!

Releases

5.2.1 2022-10-04 21:52:13

  • Fix cgi and importlib_resources deprecations. PR #185

  • Add support for Python 3.11 and drop EOL Python 3.6 PR #184

5.2.0 2022-05-31 20:42:06

  • Make the minimum version of PyJWT be v2.4.0.

5.1.0 2022-01-21 23:01:53

  • Use X-Hub-Signature-256 header for webhook validation when available. (PR #160).

  • The documentation is now built using Sphinx v>= 4.0.0. (Issue #143)

  • gidgethub.abc.GitHubAPI.getiter now accepts iterable_key parameter in order to support the Checks API. (Issue #164)

  • Accept HTTP 202 ACCEPTED as successful. (PR #174)

5.0.1 2021-04-02 03:01:58

  • Drop the machine-man-preview header from gidgethub.apps.get_installation_access_token because it is out of preview. The machine-man-preview is no longer required as of August 20, 2020. Discussion #155

5.0.0 2021-01-06 19:44:10

  • Add gidgethub.routing.Router.fetch for obtaining a frozenset of functions registered to the router that the event would be called on. Issue #74.
  • Add support for GitHub Actions Environment Files with gidgethub.actions.setenv and gidgethub.actions.addpath. Issue #137.
  • Make router callback execution order non-deterministic to avoid relying on registration order. Issue #74.
  • Fix mypy errors in gidgethub.httpx.GitHubAPI._requestIssue #133.
  • Make the minimum version of PyJWT be v2.0.0.

4.2.0 2020-08-23 04:14:47

  • gidgethub.abc.GitHubAPI.post() now accepts content_type parameter. If supplied, the content_type value will be used in the request headers, and the raw form of the data will be passed to the request. If not supplied, by default the data will be parsed as JSON, and the “application/json” content type will be used. (Issue #115).

python github async sans-io treq twisted tornado aiohttp httpx