Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ classifiers = [
"Programming Language :: Python :: 3.14",
"Topic :: Software Development",
]
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"aiohttp[speedups]~=3.8",
"gql[aiohttp,requests]>=4,<5",
Expand Down Expand Up @@ -72,7 +72,7 @@ select = [
ignore = [
"E501", # let black handle line-length
]
target-version = "py38"
target-version = "py310"

[tool.ruff.isort]
known-first-party = ["simple_github"]
Expand Down
9 changes: 4 additions & 5 deletions src/simple_github/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import asyncio
import os
from functools import partial
from typing import List, Optional, Union

from .auth import AppAuth, AppInstallationAuth, PublicAuth, TokenAuth
from .client import AsyncClient, Client, SyncClient


def client_from_env(owner: str, repositories: List[str]):
def client_from_env(owner: str, repositories: list[str]):
if "GITHUB_TOKEN" in os.environ:
return partial(TokenClient, os.environ["GITHUB_TOKEN"])
elif "GITHUB_APP_ID" in os.environ and "GITHUB_APP_PRIVKEY" in os.environ:
Expand All @@ -25,8 +24,8 @@ def client_from_env(owner: str, repositories: List[str]):
def AppClient(
id: int,
privkey: str,
owner: Optional[str] = None,
repositories: Optional[Union[List[str], str]] = None,
owner: str | None = None,
repositories: list[str] | str | None = None,
) -> Client:
"""Convenience function to create a `Client` instance authenticated
as a Github App.
Expand All @@ -41,7 +40,7 @@ def AppClient(
owner (str): The org or user where the app is installed. If not
specified, the returned client will be authenticated as the app
itself rather than as an app installation.
repositories (List[str]): A list of repositories to limit the app's
repositories (list[str]): A list of repositories to limit the app's
scope to. If not specified, the client will have access to all
repositories owned by `owner`.

Expand Down
5 changes: 3 additions & 2 deletions src/simple_github/auth.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import time
from abc import ABC, abstractmethod
from typing import Any, AsyncGenerator, AsyncIterator, List, Optional, Union
from collections.abc import AsyncGenerator, AsyncIterator
from typing import Any

import jwt

Expand Down Expand Up @@ -105,7 +106,7 @@ def __init__(
self,
app: AppAuth,
owner: str,
repositories: Optional[Union[List[str], str]] = None,
repositories: list[str] | str | None = None,
):
"""Authentication for a Github App installation.

Expand Down
25 changes: 13 additions & 12 deletions src/simple_github/client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import asyncio
import json
from abc import abstractmethod
from typing import TYPE_CHECKING, Any, Coroutine, Dict, Optional, Union
from collections.abc import Coroutine
from typing import TYPE_CHECKING, Any

from aiohttp import ClientResponse, ClientSession
from gql import Client as GqlClient
Expand All @@ -18,13 +19,13 @@
GITHUB_API_ENDPOINT = "https://api.github.com"
GITHUB_GRAPHQL_ENDPOINT = "https://api.github.com/graphql"

Response = Union[RequestsResponse, ClientResponse]
RequestData = Optional[Dict[str, Any]]
Response = RequestsResponse | ClientResponse
RequestData = dict[str, Any] | None

# Implementations of the base class can be either sync or async.
BaseDict = Union[Dict[str, Any], Coroutine[None, None, Dict[str, Any]]]
BaseNone = Union[None, Coroutine[None, None, None]]
BaseResponse = Union[Response, Coroutine[None, None, Response]]
BaseDict = dict[str, Any] | Coroutine[None, None, dict[str, Any]]
BaseNone = None | Coroutine[None, None, None]
BaseResponse = Response | Coroutine[None, None, Response]


class Client:
Expand All @@ -40,10 +41,10 @@ def __init__(self, auth: "Auth"):
"""
self.auth = auth
self._prev_token = None
self._gql_client: Optional[GqlClient] = None
self._gql_session: Optional[
Any[ReconnectingAsyncClientSession, SyncClientSession]
] = None
self._gql_client: GqlClient | None = None
self._gql_session: (
Any[ReconnectingAsyncClientSession, SyncClientSession] | None
) = None

@abstractmethod
def close(self) -> BaseNone: ...
Expand Down Expand Up @@ -196,7 +197,7 @@ def delete(self, query: str, data: RequestData = None) -> None:
"""
self.request("DELETE", query, data=json.dumps(data))

def execute(self, query: str, variables: RequestData = None) -> Dict[str, Any]:
def execute(self, query: str, variables: RequestData = None) -> dict[str, Any]:
"""Execute a query against Github's GraphQL endpoint.

Args:
Expand Down Expand Up @@ -340,7 +341,7 @@ async def delete(self, query: str, data: RequestData = None) -> None:

async def execute(
self, query: str, variables: RequestData = None
) -> Dict[str, Any]:
) -> dict[str, Any]:
"""Execute a query against Github's GraphQL endpoint.

Args:
Expand Down
2 changes: 1 addition & 1 deletion taskcluster/kinds/docker-image/kind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ tasks:
fetch: {}
python:
args:
PYTHON_VERSIONS: "3.14 3.13 3.12 3.11 3.10 3.9"
PYTHON_VERSIONS: "3.14 3.13 3.12 3.11 3.10"
UV_VERSION: 0.9.18