Skip to content

Commit ed72f14

Browse files
Drop support for python3.9 (#948)
* Drop support for `python3.9` refs: - https://devguide.python.org/versions/ * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 5c067b2 commit ed72f14

File tree

17 files changed

+41
-43
lines changed

17 files changed

+41
-43
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Python
1919
uses: actions/setup-python@v6
2020
with:
21-
python-version: '3.9'
21+
python-version: '3.10'
2222

2323
- name: Install dependencies
2424
run: |

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
fail-fast: false
1616
max-parallel: 5
1717
matrix:
18-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
18+
python-version: ['3.10', '3.11', '3.12', '3.13']
1919
django-version: ['4.2', '5.0', '5.1', '5.2']
2020
drf-version: ['3.14', '3.15']
2121
exclude:

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ repos:
5151
rev: 'v3.20.0'
5252
hooks:
5353
- id: pyupgrade
54-
args: ['--py39-plus', '--keep-mock']
54+
args: ['--py310-plus', '--keep-mock']
5555

5656
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
5757
rev: v1.0.1

docs/development_and_contributing.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ directory:
3131

3232
.. code-block:: bash
3333
34-
pyenv install 3.9.x
34+
pyenv install 3.10.x
3535
cat > .python-version <<EOF
36-
3.9.x
36+
3.10.x
3737
EOF
3838
3939
Above, the ``x`` in each case should be replaced with the latest corresponding

docs/getting_started.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Getting started
66
Requirements
77
------------
88

9-
* Python (3.9, 3.10, 3.11, 3.12, 3.13)
9+
* Python (3.10, 3.11, 3.12, 3.13)
1010
* Django (4.2, 5.0, 5.1)
1111
* Django REST Framework (3.14, 3.15)
1212

rest_framework_simplejwt/authentication.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self, *args, **kwargs) -> None:
4141
super().__init__(*args, **kwargs)
4242
self.user_model = get_user_model()
4343

44-
def authenticate(self, request: Request) -> Optional[tuple[AuthUser, Token]]:
44+
def authenticate(self, request: Request) -> tuple[AuthUser, Token] | None:
4545
header = self.get_header(request)
4646
if header is None:
4747
return None
@@ -73,7 +73,7 @@ def get_header(self, request: Request) -> bytes:
7373

7474
return header
7575

76-
def get_raw_token(self, header: bytes) -> Optional[bytes]:
76+
def get_raw_token(self, header: bytes) -> bytes | None:
7777
"""
7878
Extracts an unvalidated JSON web token from the given "Authorization"
7979
header value.
@@ -176,7 +176,7 @@ def get_user(self, validated_token: Token) -> AuthUser:
176176
JWTTokenUserAuthentication = JWTStatelessUserAuthentication
177177

178178

179-
def default_user_authentication_rule(user: Optional[AuthUser]) -> bool:
179+
def default_user_authentication_rule(user: AuthUser | None) -> bool:
180180
# Prior to Django 1.10, inactive users could be authenticated with the
181181
# default `ModelBackend`. As of Django 1.10, the `ModelBackend`
182182
# prevents inactive users from authenticating. App designers can still

rest_framework_simplejwt/backends.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ class TokenBackend:
4141
def __init__(
4242
self,
4343
algorithm: str,
44-
signing_key: Optional[str] = None,
44+
signing_key: str | None = None,
4545
verifying_key: str = "",
46-
audience: Union[str, Iterable, None] = None,
47-
issuer: Optional[str] = None,
48-
jwk_url: Optional[str] = None,
49-
leeway: Union[float, int, timedelta, None] = None,
50-
json_encoder: Optional[type[json.JSONEncoder]] = None,
46+
audience: str | Iterable | None = None,
47+
issuer: str | None = None,
48+
jwk_url: str | None = None,
49+
leeway: float | int | timedelta | None = None,
50+
json_encoder: type[json.JSONEncoder] | None = None,
5151
) -> None:
5252
self._validate_algorithm(algorithm)
5353

@@ -73,7 +73,7 @@ def prepared_signing_key(self) -> Any:
7373
def prepared_verifying_key(self) -> Any:
7474
return self._prepare_key(self.verifying_key)
7575

76-
def _prepare_key(self, key: Optional[str]) -> Any:
76+
def _prepare_key(self, key: str | None) -> Any:
7777
# Support for PyJWT 1.7.1 or empty signing key
7878
if key is None or not getattr(jwt.PyJWS, "get_algorithm_by_name", None):
7979
return key

rest_framework_simplejwt/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class DetailDictMixin:
2626

2727
def __init__(
2828
self,
29-
detail: Union[dict[str, Any], str, None] = None,
30-
code: Optional[str] = None,
29+
detail: dict[str, Any] | str | None = None,
30+
code: str | None = None,
3131
) -> None:
3232
"""
3333
Builds a detail dictionary for the error to give more information to API

rest_framework_simplejwt/models.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,16 @@ def groups(self) -> auth_models.Group:
8484
def user_permissions(self) -> auth_models.Permission:
8585
return self._user_permissions
8686

87-
def get_group_permissions(self, obj: Optional[object] = None) -> set:
87+
def get_group_permissions(self, obj: object | None = None) -> set:
8888
return set()
8989

90-
def get_all_permissions(self, obj: Optional[object] = None) -> set:
90+
def get_all_permissions(self, obj: object | None = None) -> set:
9191
return set()
9292

93-
def has_perm(self, perm: str, obj: Optional[object] = None) -> bool:
93+
def has_perm(self, perm: str, obj: object | None = None) -> bool:
9494
return False
9595

96-
def has_perms(self, perm_list: list[str], obj: Optional[object] = None) -> bool:
96+
def has_perms(self, perm_list: list[str], obj: object | None = None) -> bool:
9797
return False
9898

9999
def has_module_perms(self, module: str) -> bool:
@@ -110,6 +110,6 @@ def is_authenticated(self) -> bool:
110110
def get_username(self) -> str:
111111
return self.username
112112

113-
def __getattr__(self, attr: str) -> Optional[Any]:
113+
def __getattr__(self, attr: str) -> Any | None:
114114
"""This acts as a backup attribute getter for custom claims defined in Token serializers."""
115115
return self.token.get(attr, None)

rest_framework_simplejwt/serializers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def __init__(self, *args, **kwargs) -> None:
3131

3232
class TokenObtainSerializer(serializers.Serializer):
3333
username_field = get_user_model().USERNAME_FIELD
34-
token_class: Optional[type[Token]] = None
34+
token_class: type[Token] | None = None
3535

3636
default_error_messages = {
3737
"no_active_account": _("No active account found with the given credentials")
@@ -264,9 +264,9 @@ def validate(self, attrs: dict[str, Any]) -> dict[Any, Any]:
264264
return {}
265265

266266

267-
def default_on_login_success(user: AuthUser, request: Optional[Request]) -> None:
267+
def default_on_login_success(user: AuthUser, request: Request | None) -> None:
268268
update_last_login(None, user)
269269

270270

271-
def default_on_login_failed(credentials: dict, request: Optional[Request]) -> None:
271+
def default_on_login_failed(credentials: dict, request: Request | None) -> None:
272272
pass

0 commit comments

Comments
 (0)