diff --git a/pyproject.toml b/pyproject.toml index dcedca1..ec2fd8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", @@ -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"] diff --git a/src/simple_github/__init__.py b/src/simple_github/__init__.py index 154775c..7661381 100644 --- a/src/simple_github/__init__.py +++ b/src/simple_github/__init__.py @@ -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: @@ -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. @@ -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`. diff --git a/src/simple_github/auth.py b/src/simple_github/auth.py index 4a8f8da..d6037f8 100644 --- a/src/simple_github/auth.py +++ b/src/simple_github/auth.py @@ -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 @@ -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. diff --git a/src/simple_github/client.py b/src/simple_github/client.py index 13b59f8..057b56f 100644 --- a/src/simple_github/client.py +++ b/src/simple_github/client.py @@ -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 @@ -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: @@ -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: ... @@ -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: @@ -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: diff --git a/taskcluster/kinds/docker-image/kind.yml b/taskcluster/kinds/docker-image/kind.yml index b804e05..7a833cd 100644 --- a/taskcluster/kinds/docker-image/kind.yml +++ b/taskcluster/kinds/docker-image/kind.yml @@ -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