Skip to content
This repository was archived by the owner on Apr 26, 2025. It is now read-only.

Commit 969ec00

Browse files
committed
Drop Python 3.8 support
1 parent 05a17b6 commit 969ec00

File tree

11 files changed

+72
-70
lines changed

11 files changed

+72
-70
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
runs-on: ubuntu-latest
99
strategy:
1010
matrix:
11-
python_version: [3.8, 3.9, '3.10', '3.11', '3.12']
11+
python_version: ['3.9', '3.10', '3.11', '3.12']
1212

1313
steps:
1414
- uses: actions/checkout@v3
@@ -44,7 +44,7 @@ jobs:
4444
- name: Set up Python
4545
uses: actions/setup-python@v4
4646
with:
47-
python-version: 3.8
47+
python-version: '3.9'
4848
- name: Install dependencies
4949
shell: bash
5050
run: |

fief_client/client.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import contextlib
22
import json
33
import uuid
4+
from collections.abc import Mapping
45
from enum import Enum
5-
from typing import Any, Dict, List, Mapping, Optional, Tuple, TypedDict, Union
6+
from typing import Any, Optional, TypedDict, Union
67
from urllib.parse import urlencode, urlsplit, urlunsplit
78

89
import httpx
@@ -87,11 +88,11 @@ class FiefAccessTokenInfo(TypedDict):
8788

8889
id: uuid.UUID
8990
"""ID of the user."""
90-
scope: List[str]
91+
scope: list[str]
9192
"""List of granted scopes for this access token."""
9293
acr: FiefACR
9394
"""Level of Authentication Context class Reference."""
94-
permissions: List[str]
95+
permissions: list[str]
9596
"""List of [granted permissions](https://docs.fief.dev/getting-started/access-control/) for this user."""
9697
access_token: str
9798
"""Access token you can use to call the Fief API."""
@@ -128,7 +129,7 @@ class FiefUserInfo(TypedDict):
128129
"""
129130
ID of the [tenant](https://docs.fief.dev/getting-started/tenants/) associated to the user.
130131
"""
131-
fields: Dict[str, Any]
132+
fields: dict[str, Any]
132133
"""
133134
[User fields](https://docs.fief.dev/getting-started/user-fields/) values for this user, indexed by their slug.
134135
"""
@@ -192,7 +193,7 @@ class BaseFief:
192193
encryption_key: Optional[jwk.JWK] = None
193194
""""""
194195

195-
_openid_configuration: Optional[Dict[str, Any]] = None
196+
_openid_configuration: Optional[dict[str, Any]] = None
196197
_jwks: Optional[jwk.JWKSet] = None
197198

198199
_verify: VerifyTypes
@@ -236,7 +237,7 @@ def __init__(
236237

237238
def _get_endpoint_url(
238239
self,
239-
openid_configuration: Dict[str, Any],
240+
openid_configuration: dict[str, Any],
240241
field: str,
241242
*,
242243
absolute: bool = False,
@@ -261,11 +262,11 @@ def _get_endpoint_url(
261262

262263
def _auth_url(
263264
self,
264-
openid_configuration: Dict[str, Any],
265+
openid_configuration: dict[str, Any],
265266
redirect_uri: str,
266267
*,
267268
state: Optional[str] = None,
268-
scope: Optional[List[str]] = None,
269+
scope: Optional[list[str]] = None,
269270
code_challenge: Optional[str] = None,
270271
code_challenge_method: Optional[str] = None,
271272
lang: Optional[str] = None,
@@ -303,9 +304,9 @@ def _validate_access_token(
303304
access_token: str,
304305
jwks: jwk.JWKSet,
305306
*,
306-
required_scope: Optional[List[str]] = None,
307+
required_scope: Optional[list[str]] = None,
307308
required_acr: Optional[FiefACR] = None,
308-
required_permissions: Optional[List[str]] = None,
309+
required_permissions: Optional[list[str]] = None,
309310
) -> FiefAccessTokenInfo:
310311
try:
311312
decoded_token = jwt.JWT(jwt=access_token, algs=["RS256"], key=jwks)
@@ -325,7 +326,7 @@ def _validate_access_token(
325326
if acr < required_acr:
326327
raise FiefAccessTokenACRTooLow()
327328

328-
permissions: List[str] = claims["permissions"]
329+
permissions: list[str] = claims["permissions"]
329330
if required_permissions is not None:
330331
for required_permission in required_permissions:
331332
if required_permission not in permissions:
@@ -406,7 +407,7 @@ def _get_auth_refresh_token_request(
406407
*,
407408
endpoint: str,
408409
refresh_token: str,
409-
scope: Optional[List[str]] = None,
410+
scope: Optional[list[str]] = None,
410411
) -> httpx.Request:
411412
data = {
412413
"client_id": self.client_id,
@@ -433,7 +434,7 @@ def _get_update_profile_request(
433434
*,
434435
endpoint: str,
435436
access_token: str,
436-
data: Dict[str, Any],
437+
data: dict[str, Any],
437438
) -> httpx.Request:
438439
return client.build_request(
439440
"PATCH",
@@ -521,7 +522,7 @@ def auth_url(
521522
redirect_uri: str,
522523
*,
523524
state: Optional[str] = None,
524-
scope: Optional[List[str]] = None,
525+
scope: Optional[list[str]] = None,
525526
code_challenge: Optional[str] = None,
526527
code_challenge_method: Optional[str] = None,
527528
lang: Optional[str] = None,
@@ -561,7 +562,7 @@ def auth_url(
561562

562563
def auth_callback(
563564
self, code: str, redirect_uri: str, *, code_verifier: Optional[str] = None
564-
) -> Tuple[FiefTokenResponse, FiefUserInfo]:
565+
) -> tuple[FiefTokenResponse, FiefUserInfo]:
565566
"""
566567
Return a `FiefTokenResponse` and `FiefUserInfo` in exchange of an authorization code.
567568
@@ -589,8 +590,8 @@ def auth_callback(
589590
return token_response, userinfo
590591

591592
def auth_refresh_token(
592-
self, refresh_token: str, *, scope: Optional[List[str]] = None
593-
) -> Tuple[FiefTokenResponse, FiefUserInfo]:
593+
self, refresh_token: str, *, scope: Optional[list[str]] = None
594+
) -> tuple[FiefTokenResponse, FiefUserInfo]:
594595
"""
595596
Return fresh `FiefTokenResponse` and `FiefUserInfo` in exchange of a refresh token
596597
@@ -632,9 +633,9 @@ def validate_access_token(
632633
self,
633634
access_token: str,
634635
*,
635-
required_scope: Optional[List[str]] = None,
636+
required_scope: Optional[list[str]] = None,
636637
required_acr: Optional[FiefACR] = None,
637-
required_permissions: Optional[List[str]] = None,
638+
required_permissions: Optional[list[str]] = None,
638639
) -> FiefAccessTokenInfo:
639640
"""
640641
Check if an access token is valid and optionally that it has a required list of scopes,
@@ -726,7 +727,7 @@ def userinfo(self, access_token: str) -> FiefUserInfo:
726727

727728
return response.json()
728729

729-
def update_profile(self, access_token: str, data: Dict[str, Any]) -> FiefUserInfo:
730+
def update_profile(self, access_token: str, data: dict[str, Any]) -> FiefUserInfo:
730731
"""
731732
Update user information with the Fief API using a valid access token.
732733
@@ -877,7 +878,7 @@ def _get_httpx_client(self):
877878
) as client:
878879
yield client
879880

880-
def _get_openid_configuration(self) -> Dict[str, Any]:
881+
def _get_openid_configuration(self) -> dict[str, Any]:
881882
if self._openid_configuration is not None:
882883
return self._openid_configuration
883884

@@ -948,7 +949,7 @@ async def auth_url(
948949
redirect_uri: str,
949950
*,
950951
state: Optional[str] = None,
951-
scope: Optional[List[str]] = None,
952+
scope: Optional[list[str]] = None,
952953
code_challenge: Optional[str] = None,
953954
code_challenge_method: Optional[str] = None,
954955
lang: Optional[str] = None,
@@ -988,7 +989,7 @@ async def auth_url(
988989

989990
async def auth_callback(
990991
self, code: str, redirect_uri: str, *, code_verifier: Optional[str] = None
991-
) -> Tuple[FiefTokenResponse, FiefUserInfo]:
992+
) -> tuple[FiefTokenResponse, FiefUserInfo]:
992993
"""
993994
Return a `FiefTokenResponse` and `FiefUserInfo` in exchange of an authorization code.
994995
@@ -1016,8 +1017,8 @@ async def auth_callback(
10161017
return token_response, userinfo
10171018

10181019
async def auth_refresh_token(
1019-
self, refresh_token: str, *, scope: Optional[List[str]] = None
1020-
) -> Tuple[FiefTokenResponse, FiefUserInfo]:
1020+
self, refresh_token: str, *, scope: Optional[list[str]] = None
1021+
) -> tuple[FiefTokenResponse, FiefUserInfo]:
10211022
"""
10221023
Return fresh `FiefTokenResponse` and `FiefUserInfo` in exchange of a refresh token
10231024
@@ -1060,9 +1061,9 @@ async def validate_access_token(
10601061
self,
10611062
access_token: str,
10621063
*,
1063-
required_scope: Optional[List[str]] = None,
1064+
required_scope: Optional[list[str]] = None,
10641065
required_acr: Optional[FiefACR] = None,
1065-
required_permissions: Optional[List[str]] = None,
1066+
required_permissions: Optional[list[str]] = None,
10661067
) -> FiefAccessTokenInfo:
10671068
"""
10681069
Check if an access token is valid and optionally that it has a required list of scopes,
@@ -1155,7 +1156,7 @@ async def userinfo(self, access_token: str) -> FiefUserInfo:
11551156
return response.json()
11561157

11571158
async def update_profile(
1158-
self, access_token: str, data: Dict[str, Any]
1159+
self, access_token: str, data: dict[str, Any]
11591160
) -> FiefUserInfo:
11601161
"""
11611162
Update user information with the Fief API using a valid access token.
@@ -1309,7 +1310,7 @@ async def _get_httpx_client(self):
13091310
) as client:
13101311
yield client
13111312

1312-
async def _get_openid_configuration(self) -> Dict[str, Any]:
1313+
async def _get_openid_configuration(self) -> dict[str, Any]:
13131314
if self._openid_configuration is not None:
13141315
return self._openid_configuration
13151316

fief_client/integrations/cli.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,13 @@ def current_user(self, refresh: bool = False) -> FiefUserInfo:
179179

180180
def authorize(
181181
self,
182-
server_address: typing.Tuple[str, int] = ("localhost", 51562),
182+
server_address: tuple[str, int] = ("localhost", 51562),
183183
redirect_path: str = "/callback",
184184
*,
185-
scope: typing.Optional[typing.List[str]] = None,
185+
scope: typing.Optional[list[str]] = None,
186186
lang: typing.Optional[str] = None,
187187
extras_params: typing.Optional[typing.Mapping[str, str]] = None,
188-
) -> typing.Tuple[FiefTokenResponse, FiefUserInfo]:
188+
) -> tuple[FiefTokenResponse, FiefUserInfo]:
189189
"""
190190
Perform a user authentication with the Fief server.
191191
@@ -217,7 +217,7 @@ def authorize(
217217
"""
218218
redirect_uri = f"http://{server_address[0]}:{server_address[1]}{redirect_path}"
219219

220-
scope_set: typing.Set[str] = set(scope) if scope else set()
220+
scope_set: set[str] = set(scope) if scope else set()
221221
scope_set.add("openid")
222222
scope_set.add("offline_access")
223223

@@ -304,7 +304,7 @@ def render_success_page(self) -> str:
304304
</html>
305305
"""
306306

307-
def render_error_page(self, query_params: typing.Dict[str, typing.Any]) -> str:
307+
def render_error_page(self, query_params: dict[str, typing.Any]) -> str:
308308
"""
309309
Generate the HTML page that'll be shown to the user when something goes wrong during redirection.
310310

fief_client/integrations/fastapi.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
"""FastAPI integration."""
22

33
import uuid
4+
from collections.abc import AsyncGenerator, Coroutine, Generator
45
from inspect import Parameter, Signature, isawaitable
56
from typing import (
6-
AsyncGenerator,
77
Callable,
8-
Coroutine,
9-
Generator,
10-
List,
118
Optional,
129
Protocol,
1310
TypeVar,
@@ -126,9 +123,9 @@ def __init__(
126123
def authenticated(
127124
self,
128125
optional: bool = False,
129-
scope: Optional[List[str]] = None,
126+
scope: Optional[list[str]] = None,
130127
acr: Optional[FiefACR] = None,
131-
permissions: Optional[List[str]] = None,
128+
permissions: Optional[list[str]] = None,
132129
):
133130
"""
134131
Return a FastAPI dependency to check if a request is authenticated.
@@ -198,9 +195,9 @@ async def _authenticated(
198195
def current_user(
199196
self,
200197
optional: bool = False,
201-
scope: Optional[List[str]] = None,
198+
scope: Optional[list[str]] = None,
202199
acr: Optional[FiefACR] = None,
203-
permissions: Optional[List[str]] = None,
200+
permissions: Optional[list[str]] = None,
204201
refresh: bool = False,
205202
):
206203
"""
@@ -296,7 +293,7 @@ def _get_authenticated_call_signature(self, scheme: SecurityBase) -> Signature:
296293
with a dynamic security scheme dependency at runtime.
297294
This way, it's detected by the OpenAPI generator.
298295
"""
299-
parameters: List[Parameter] = [
296+
parameters: list[Parameter] = [
300297
Parameter(
301298
name="request",
302299
kind=Parameter.POSITIONAL_OR_KEYWORD,
@@ -324,7 +321,7 @@ def _get_current_user_call_signature(self, authenticated: Callable) -> Signature
324321
with a dynamic security scheme dependency at runtime.
325322
This way, it's detected by the OpenAPI generator.
326323
"""
327-
parameters: List[Parameter] = [
324+
parameters: list[Parameter] = [
328325
Parameter(
329326
name="access_token_info",
330327
kind=Parameter.POSITIONAL_OR_KEYWORD,

fief_client/integrations/flask.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import uuid
44
from functools import wraps
5-
from typing import Callable, List, Optional
5+
from typing import Callable, Optional
66

77
from flask import g, request
88

@@ -168,9 +168,9 @@ def authenticated(
168168
self,
169169
*,
170170
optional: bool = False,
171-
scope: Optional[List[str]] = None,
171+
scope: Optional[list[str]] = None,
172172
acr: Optional[FiefACR] = None,
173-
permissions: Optional[List[str]] = None,
173+
permissions: Optional[list[str]] = None,
174174
):
175175
"""
176176
Decorator to check if a request is authenticated.
@@ -239,9 +239,9 @@ def current_user(
239239
self,
240240
*,
241241
optional: bool = False,
242-
scope: Optional[List[str]] = None,
242+
scope: Optional[list[str]] = None,
243243
acr: Optional[FiefACR] = None,
244-
permissions: Optional[List[str]] = None,
244+
permissions: Optional[list[str]] = None,
245245
refresh: bool = False,
246246
):
247247
"""

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module = "yaspin.*"
77
ignore_missing_imports = true
88

99
[tool.ruff]
10-
target-version = "py38"
10+
target-version = "py39"
1111

1212
[tool.ruff.lint]
1313
extend-select = ["I", "UP", "TRY"]
@@ -88,15 +88,14 @@ license = "MIT"
8888
classifiers = [
8989
"License :: OSI Approved :: MIT License",
9090
"Intended Audience :: Developers",
91-
"Programming Language :: Python :: 3.8",
9291
"Programming Language :: Python :: 3.9",
9392
"Programming Language :: Python :: 3.10",
9493
"Programming Language :: Python :: 3.11",
9594
"Programming Language :: Python :: 3.12",
9695
"Programming Language :: Python :: 3 :: Only",
9796
]
9897
dynamic = ["version"]
99-
requires-python = ">=3.8"
98+
requires-python = ">=3.9"
10099
dependencies = [
101100
"httpx >=0.21.3,<0.28.0",
102101
"jwcrypto >=1.4,<2.0.0",

0 commit comments

Comments
 (0)