diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c54bc04..a88752f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,28 +16,28 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.10-dev", "3.11-dev"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"] include: - - { python-version: "3.7", nox-python-version: "3.7" } - { python-version: "3.8", nox-python-version: "3.8" } - { python-version: "3.9", nox-python-version: "3.9" } - { python-version: "3.10", nox-python-version: "3.10" } - - { python-version: "3.10-dev", nox-python-version: "3.10" } - - { python-version: "3.11-dev", nox-python-version: "3.11" } + - { python-version: "3.11", nox-python-version: "3.11" } + - { python-version: "3.12", nox-python-version: "3.12" } + - { python-version: "3.13-dev", nox-python-version: "3.13" } steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} restore-keys: | ${{ runner.os }}-pip- - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 if: "!endsWith(matrix.python-version, '-dev')" with: python-version: ${{ matrix.python-version }} - - uses: deadsnakes/action@v2.1.1 + - uses: deadsnakes/action@v3.1.0 if: endsWith(matrix.python-version, '-dev') with: python-version: ${{ matrix.python-version }} @@ -45,7 +45,7 @@ jobs: - run: nox --session tests-${{ matrix.nox-python-version }} env: PYTHONDEVMODE: 1 - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 if: always() with: token: ${{ secrets.CODECOV_TOKEN }} @@ -55,14 +55,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} restore-keys: | ${{ runner.os }}-pip- - - uses: actions/setup-python@v3 + - uses: actions/setup-python@v5 with: python-version: "3.10" - run: pip install nox diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 969ca97..f56c4f9 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ sphinx: build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3" python: install: diff --git a/README.rst b/README.rst index 0fd389d..7355021 100644 --- a/README.rst +++ b/README.rst @@ -25,7 +25,7 @@ Gidgethub is `available on PyPI `_. python3 -m pip install gidgethub -Gidgethub requires Python version 3.7 and up. +Gidgethub requires Python version 3.8 and up. Goals diff --git a/gidgethub/__init__.py b/gidgethub/__init__.py index 42be3b9..cc65f10 100644 --- a/gidgethub/__init__.py +++ b/gidgethub/__init__.py @@ -1,4 +1,5 @@ """An async GitHub API library""" + __version__ = "5.3.0" import http @@ -6,19 +7,16 @@ class GitHubException(Exception): - """Base exception for this library.""" class ValidationFailure(GitHubException): - """An exception representing failed validation of a webhook event.""" # https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/securing-your-webhooks#validating-payloads-from-github class HTTPException(GitHubException): - """A general exception to represent HTTP responses.""" def __init__(self, status_code: http.HTTPStatus, *args: Any) -> None: @@ -30,7 +28,6 @@ def __init__(self, status_code: http.HTTPStatus, *args: Any) -> None: class RedirectionException(HTTPException): - """Exception for 3XX HTTP responses.""" @@ -44,7 +41,6 @@ class BadRequest(HTTPException): class BadRequestUnknownError(BadRequest): - """A bad request whose response body is not JSON.""" def __init__(self, response: str) -> None: @@ -53,7 +49,6 @@ def __init__(self, response: str) -> None: class RateLimitExceeded(BadRequest): - """Request rejected due to the rate limit being exceeded.""" # Technically rate_limit is of type gidgethub.sansio.RateLimit, but a @@ -68,7 +63,6 @@ def __init__(self, rate_limit: Any, *args: Any) -> None: class InvalidField(BadRequest): - """A field in the request is invalid. Represented by a 422 HTTP Response. Details of what fields were @@ -82,7 +76,6 @@ def __init__(self, errors: Any, *args: Any) -> None: class ValidationError(BadRequest): - """A request was unable to be completed. Represented by a 422 HTTP response. Details of what went wrong @@ -96,12 +89,10 @@ def __init__(self, errors: Any, *args: Any) -> None: class GitHubBroken(HTTPException): - """Exception for 5XX HTTP responses.""" class GraphQLException(GitHubException): - """Base exception for the GraphQL v4 API.""" def __init__(self, message: str, response: Any) -> None: @@ -110,7 +101,6 @@ def __init__(self, message: str, response: Any) -> None: class BadGraphQLRequest(GraphQLException): - """A 4XX HTTP response.""" def __init__(self, status_code: http.HTTPStatus, response: Any) -> None: @@ -120,7 +110,6 @@ def __init__(self, status_code: http.HTTPStatus, response: Any) -> None: class GraphQLAuthorizationFailure(BadGraphQLRequest): - """401 HTTP response to a bad oauth token.""" def __init__(self, response: Any) -> None: @@ -128,7 +117,6 @@ def __init__(self, response: Any) -> None: class QueryError(GraphQLException): - """An error occurred while attempting to handle a GraphQL v4 query.""" def __init__(self, response: Any) -> None: @@ -136,7 +124,6 @@ def __init__(self, response: Any) -> None: class GraphQLResponseTypeError(GraphQLException): - """The GraphQL response has an unexpected content type.""" def __init__(self, content_type: Optional[str], response: Any) -> None: diff --git a/gidgethub/abc.py b/gidgethub/abc.py index e15d9f6..00f6d70 100644 --- a/gidgethub/abc.py +++ b/gidgethub/abc.py @@ -1,4 +1,5 @@ """Provide an abstract base class for easier requests.""" + import abc import http import json @@ -29,7 +30,6 @@ class GitHubAPI(abc.ABC): - """Provide an idiomatic API for making calls to GitHub's API.""" def __init__( diff --git a/gidgethub/actions.py b/gidgethub/actions.py index 5be6a33..36f99a6 100644 --- a/gidgethub/actions.py +++ b/gidgethub/actions.py @@ -1,4 +1,5 @@ """Support for GitHub Actions.""" + import functools import json import os diff --git a/gidgethub/apps.py b/gidgethub/apps.py index 06da0ce..323a095 100644 --- a/gidgethub/apps.py +++ b/gidgethub/apps.py @@ -1,4 +1,5 @@ """Support for GitHub Actions.""" + from typing import cast, Any, Dict import time diff --git a/gidgethub/routing.py b/gidgethub/routing.py index 10e4208..7e2989b 100644 --- a/gidgethub/routing.py +++ b/gidgethub/routing.py @@ -7,7 +7,6 @@ class Router: - """Route webhook events to registered functions.""" def __init__(self, *other_routers: "Router") -> None: diff --git a/gidgethub/sansio.py b/gidgethub/sansio.py index a3bc964..414daac 100644 --- a/gidgethub/sansio.py +++ b/gidgethub/sansio.py @@ -5,6 +5,7 @@ when working with GitHub's API (e.g. validating webhook events or specifying the API version you want your request to work against). """ + import datetime from email.message import Message import hmac @@ -93,7 +94,6 @@ def validate_event(payload: bytes, *, signature: str, secret: str) -> None: class Event: - """Details of a GitHub webhook event.""" def __init__(self, data: Any, *, event: str, delivery_id: str) -> None: @@ -219,7 +219,6 @@ def create_headers( class RateLimit: - """The rate limit imposed upon the requester. The 'limit' attribute specifies the rate of requests per hour the client is diff --git a/noxfile.py b/noxfile.py index 3049105..5f698c8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -3,22 +3,10 @@ def install_flit_dev_deps(session): session.install("flit") - # TEMP for 3.11 - if session.python == "3.11": - env = { - # https://github.com/aio-libs/aiohttp/issues/6600 - "AIOHTTP_NO_EXTENSIONS": "1", - # https://github.com/aio-libs/frozenlist/issues/285 - "FROZENLIST_NO_EXTENSIONS": "1", - # https://github.com/aio-libs/yarl/issues/680 - "YARL_NO_EXTENSIONS": "1", - } - else: - env = {} - session.run("flit", "install", "--deps", "develop", env=env) + session.run("flit", "install", "--deps", "develop") -@nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11"]) +@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]) def tests(session): install_flit_dev_deps(session) session.run("pytest", "--cov=gidgethub", "--cov-report=xml", "-n=auto", "tests") diff --git a/pyproject.toml b/pyproject.toml index 107c337..ddc3560 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ requires = [ "uritemplate>=3.0.1", "PyJWT[crypto]>=2.4.0" ] -requires-python = ">=3.7" +requires-python = ">=3.8" license = "Apache" keywords = "github sans-io async" description-file = "README.rst" @@ -18,11 +18,12 @@ classifiers = ["Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] [tool.flit.metadata.requires-extra] diff --git a/tests/samples/convert_headers.py b/tests/samples/convert_headers.py index de912ac..160513c 100644 --- a/tests/samples/convert_headers.py +++ b/tests/samples/convert_headers.py @@ -3,6 +3,7 @@ All keys will be lowercase and the status code will be used for the file name. """ + import json import sys diff --git a/tests/test_abc.py b/tests/test_abc.py index c3b7b64..ac04f96 100644 --- a/tests/test_abc.py +++ b/tests/test_abc.py @@ -777,7 +777,6 @@ async def test_no_cache(self): class TestGraphQL: - """Test gidgethub.abc.GitHubAPI.graphql().""" def gh_and_response(self, payload_filename): diff --git a/tests/test_actions.py b/tests/test_actions.py index ecff0e5..0031eda 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -32,7 +32,6 @@ def tmp_pathfile(tmpdir, tmp_path, monkeypatch): class TestWorkspace: - """Tests for gidgethub.actions.workspace().""" def test_reading(self, tmp_path, monkeypatch): @@ -49,7 +48,6 @@ def test_caching(self, tmp_path, monkeypatch): class TestEvent: - """Tests for gidgethub.actions.event().""" def test_reading(self, tmp_webhook): @@ -67,7 +65,6 @@ def test_caching(self, tmp_webhook): class TestCommand: - """Tests for gidgethub.actions.command().""" # https://help.github.com/en/actions/reference/development-tools-for-github-actions#logging-commands @@ -123,7 +120,6 @@ def test_resume_command(self, capsys): class TestSetenv: - """Tests for gidgethub.actions.setenv().""" def test_creating(self, tmp_envfile): @@ -168,7 +164,6 @@ def test_creating_multiline(self, tmp_envfile): class TestAddpath: - """Tests for gidgethub.actions.addpath().""" def test_string_path(self, tmp_pathfile): diff --git a/tests/test_apps.py b/tests/test_apps.py index 12a579b..9a7c139 100644 --- a/tests/test_apps.py +++ b/tests/test_apps.py @@ -11,7 +11,6 @@ class TestGitHubAppUtils: - """Tests for GitHub App utilities.""" @mock.patch("time.time") diff --git a/tests/test_sansio.py b/tests/test_sansio.py index c97d63f..5492de3 100644 --- a/tests/test_sansio.py +++ b/tests/test_sansio.py @@ -21,7 +21,6 @@ class TestValidateEvent: - """Tests for gidgethub.sansio.validate_event().""" secret = "123456" @@ -50,7 +49,6 @@ def test_failure(self): class TestEvent: - """Tests for gidgethub.sansio.Event.""" data = {"action": "opened"} @@ -143,7 +141,6 @@ def test_from_http_no_signature(self): class TestAcceptFormat: - """Tests for gidgethub.sansio.accept_format().""" def test_defaults(self): @@ -163,7 +160,6 @@ def test_version(self): class TestCreateHeaders: - """Tests for gidgethub.sansio.create_headers().""" def test_common_case(self): @@ -283,7 +279,6 @@ def sample(directory, status_code): class TestDecipherResponse: - """Tests for gidgethub.sansio.decipher_response().""" def test_5XX(self): @@ -553,7 +548,6 @@ def test_no_ratelimit(self): class TestFormatUrl: - """Tests for gidgethub.sansio.format_url().""" @pytest.mark.parametrize(