Skip to content

Commit

Permalink
Add support for Python 3.12 (#910)
Browse files Browse the repository at this point in the history
* Add support for Python 3.12

* Only attempt deploy for upstream

* Drop support for EOL Python 3.7

* Upgrade syntax with pyupgrade --py38-plus
  • Loading branch information
hugovk authored Aug 18, 2023
1 parent 349af0f commit fbd40eb
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 42 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,20 @@ jobs:
name: "Python ${{ matrix.python-version }} on ${{ matrix.platform }}"
runs-on: "${{ matrix.platform }}"
env:
USING_COVERAGE: '3.7,3.8'
USING_COVERAGE: '3.8'

strategy:
matrix:
platform: ["ubuntu-latest", "windows-latest"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8", "pypy-3.9"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.8", "pypy3.9"]

steps:
- uses: "actions/checkout@v3"
- uses: "actions/setup-python@v4"

with:
python-version: "${{ matrix.python-version }}"
allow-prereleases: true

- name: "Install dependencies"
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pypi-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
release-test-pypi:
name: Publish in-dev package to test.pypi.org
environment: release-test-pypi
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
if: github.repository_owner == 'jpadilla' && github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
needs: build-package

Expand All @@ -54,7 +54,7 @@ jobs:
release-pypi:
name: Publish released package to pypi.org
environment: release-pypi
if: github.event.action == 'published'
if: github.repository_owner == 'jpadilla' && github.event.action == 'published'
runs-on: ubuntu-latest
needs: build-package

Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ repos:
rev: 23.7.0
hooks:
- id: black
args: ["--target-version=py37"]
args: ["--target-version=py38"]

- repo: https://github.com/asottile/blacken-docs
rev: 1.15.0
hooks:
- id: blacken-docs
args: ["--target-version=py37"]
args: ["--target-version=py38"]

- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
Expand Down
25 changes: 7 additions & 18 deletions jwt/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import hashlib
import hmac
import json
import sys
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, ClassVar, NoReturn, Union, cast, overload
from typing import TYPE_CHECKING, Any, ClassVar, Literal, NoReturn, cast, overload

from .exceptions import InvalidKeyError
from .types import HashlibHash, JWKDict
Expand All @@ -21,12 +20,6 @@
to_base64url_uint,
)

if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal


try:
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
Expand Down Expand Up @@ -205,7 +198,7 @@ def to_jwk(key_obj, as_dict: Literal[False] = False) -> str:

@staticmethod
@abstractmethod
def to_jwk(key_obj, as_dict: bool = False) -> Union[JWKDict, str]:
def to_jwk(key_obj, as_dict: bool = False) -> JWKDict | str:
"""
Serializes a given key into a JWK
"""
Expand Down Expand Up @@ -283,7 +276,7 @@ def to_jwk(key_obj: str | bytes, as_dict: Literal[False] = False) -> str:
... # pragma: no cover

@staticmethod
def to_jwk(key_obj: str | bytes, as_dict: bool = False) -> Union[JWKDict, str]:
def to_jwk(key_obj: str | bytes, as_dict: bool = False) -> JWKDict | str:
jwk = {
"k": base64url_encode(force_bytes(key_obj)).decode(),
"kty": "oct",
Expand Down Expand Up @@ -363,9 +356,7 @@ def to_jwk(key_obj: AllowedRSAKeys, as_dict: Literal[False] = False) -> str:
... # pragma: no cover

@staticmethod
def to_jwk(
key_obj: AllowedRSAKeys, as_dict: bool = False
) -> Union[JWKDict, str]:
def to_jwk(key_obj: AllowedRSAKeys, as_dict: bool = False) -> JWKDict | str:
obj: dict[str, Any] | None = None

if hasattr(key_obj, "private_numbers"):
Expand Down Expand Up @@ -533,7 +524,7 @@ def sign(self, msg: bytes, key: EllipticCurvePrivateKey) -> bytes:

return der_to_raw_signature(der_sig, key.curve)

def verify(self, msg: bytes, key: "AllowedECKeys", sig: bytes) -> bool:
def verify(self, msg: bytes, key: AllowedECKeys, sig: bytes) -> bool:
try:
der_sig = raw_to_der_signature(sig, key.curve)
except ValueError:
Expand Down Expand Up @@ -561,9 +552,7 @@ def to_jwk(key_obj: AllowedECKeys, as_dict: Literal[False] = False) -> str:
... # pragma: no cover

@staticmethod
def to_jwk(
key_obj: AllowedECKeys, as_dict: bool = False
) -> Union[JWKDict, str]:
def to_jwk(key_obj: AllowedECKeys, as_dict: bool = False) -> JWKDict | str:
if isinstance(key_obj, EllipticCurvePrivateKey):
public_numbers = key_obj.public_key().public_numbers()
elif isinstance(key_obj, EllipticCurvePublicKey):
Expand Down Expand Up @@ -780,7 +769,7 @@ def to_jwk(key: AllowedOKPKeys, as_dict: Literal[False] = False) -> str:
... # pragma: no cover

@staticmethod
def to_jwk(key: AllowedOKPKeys, as_dict: bool = False) -> Union[JWKDict, str]:
def to_jwk(key: AllowedOKPKeys, as_dict: bool = False) -> JWKDict | str:
if isinstance(key, (Ed25519PublicKey, Ed448PublicKey)):
x = key.public_bytes(
encoding=Encoding.Raw,
Expand Down
10 changes: 5 additions & 5 deletions jwt/api_jwk.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ def __init__(self, jwk_data: JWKDict, algorithm: str | None = None) -> None:
self.key = self.Algorithm.from_jwk(self._jwk_data)

@staticmethod
def from_dict(obj: JWKDict, algorithm: str | None = None) -> "PyJWK":
def from_dict(obj: JWKDict, algorithm: str | None = None) -> PyJWK:
return PyJWK(obj, algorithm)

@staticmethod
def from_json(data: str, algorithm: None = None) -> "PyJWK":
def from_json(data: str, algorithm: None = None) -> PyJWK:
obj = json.loads(data)
return PyJWK.from_dict(obj, algorithm)

Expand Down Expand Up @@ -104,16 +104,16 @@ def __init__(self, keys: list[JWKDict]) -> None:
)

@staticmethod
def from_dict(obj: dict[str, Any]) -> "PyJWKSet":
def from_dict(obj: dict[str, Any]) -> PyJWKSet:
keys = obj.get("keys", [])
return PyJWKSet(keys)

@staticmethod
def from_json(data: str) -> "PyJWKSet":
def from_json(data: str) -> PyJWKSet:
obj = json.loads(data)
return PyJWKSet.from_dict(obj)

def __getitem__(self, kid: str) -> "PyJWK":
def __getitem__(self, kid: str) -> PyJWK:
for key in self.keys:
if key.key_id == kid:
return key
Expand Down
6 changes: 2 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,18 @@ classifiers =
Programming Language :: Python
Programming Language :: Python :: 3
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
Topic :: Utilities

[options]
zip_safe = false
include_package_data = true
python_requires = >=3.7
python_requires = >=3.8
packages = find:
install_requires =
typing_extensions; python_version<="3.7"

[options.package_data]
* = py.typed
Expand Down
4 changes: 1 addition & 3 deletions tests/test_api_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,7 @@ def test_raise_exception_audience_as_bytes(self, jwt):
payload = {"some": "payload", "aud": ["urn:me", "urn:someone-else"]}
token = jwt.encode(payload, "secret")
with pytest.raises(InvalidAudienceError):
jwt.decode(
token, "secret", audience="urn:me".encode(), algorithms=["HS256"]
)
jwt.decode(token, "secret", audience=b"urn:me", algorithms=["HS256"])

def test_raise_exception_invalid_audience_in_array(self, jwt):
payload = {
Expand Down
12 changes: 6 additions & 6 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ filterwarnings =

[gh-actions]
python =
3.7: py37, docs
3.8: py38, typing
3.9: py39
3.10: py310
3.11: py311
pypy-3.8: pypy3
pypy-3.9: pypy3
3.11: py311, docs
3.12: py312
pypy3.8: pypy3
pypy3.9: pypy3


[tox]
envlist =
lint
typing
py{37,38,39,310,311,py3}-{crypto,nocrypto}
py{38,39,310,311,312,py3}-{crypto,nocrypto}
docs
pypi-description
coverage-report
Expand All @@ -40,7 +40,7 @@ commands = {envpython} -b -m coverage run -m pytest {posargs}


[testenv:docs]
basepython = python3.7
basepython = python3.11
extras = docs
commands =
sphinx-build -n -T -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
Expand Down

0 comments on commit fbd40eb

Please sign in to comment.