mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2026-03-13 07:49:55 +08:00
Drop Python 3.8 support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import re
|
||||
from collections.abc import Sequence
|
||||
from inspect import Parameter, Signature
|
||||
from typing import Any, Callable, Generic, List, Optional, Sequence, Tuple, cast
|
||||
from typing import Any, Callable, Generic, Optional, cast
|
||||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from makefun import with_signature
|
||||
@@ -160,7 +161,7 @@ class Authenticator(Generic[models.UP, models.ID]):
|
||||
verified: bool = False,
|
||||
superuser: bool = False,
|
||||
**kwargs,
|
||||
) -> Tuple[Optional[models.UP], Optional[str]]:
|
||||
) -> tuple[Optional[models.UP], Optional[str]]:
|
||||
user: Optional[models.UP] = None
|
||||
token: Optional[str] = None
|
||||
enabled_backends: Sequence[AuthenticationBackend[models.UP, models.ID]] = (
|
||||
@@ -203,7 +204,7 @@ class Authenticator(Generic[models.UP, models.ID]):
|
||||
This way, each security schemes are detected by the OpenAPI generator.
|
||||
"""
|
||||
try:
|
||||
parameters: List[Parameter] = [
|
||||
parameters: list[Parameter] = [
|
||||
Parameter(
|
||||
name="user_manager",
|
||||
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Generic, Optional, Protocol
|
||||
from typing import Any, Generic, Optional, Protocol
|
||||
|
||||
from fastapi_users.authentication.strategy.db.models import AP
|
||||
|
||||
@@ -13,11 +13,11 @@ class AccessTokenDatabase(Protocol, Generic[AP]):
|
||||
"""Get a single access token by token."""
|
||||
... # pragma: no cover
|
||||
|
||||
async def create(self, create_dict: Dict[str, Any]) -> AP:
|
||||
async def create(self, create_dict: dict[str, Any]) -> AP:
|
||||
"""Create an access token."""
|
||||
... # pragma: no cover
|
||||
|
||||
async def update(self, access_token: AP, update_dict: Dict[str, Any]) -> AP:
|
||||
async def update(self, access_token: AP, update_dict: dict[str, Any]) -> AP:
|
||||
"""Update an access token."""
|
||||
... # pragma: no cover
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import secrets
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Dict, Generic, Optional
|
||||
from typing import Any, Generic, Optional
|
||||
|
||||
from fastapi_users import exceptions, models
|
||||
from fastapi_users.authentication.strategy.base import Strategy
|
||||
@@ -50,6 +50,6 @@ class DatabaseStrategy(
|
||||
if access_token is not None:
|
||||
await self.database.delete(access_token)
|
||||
|
||||
def _create_access_token_dict(self, user: models.UP) -> Dict[str, Any]:
|
||||
def _create_access_token_dict(self, user: models.UP) -> dict[str, Any]:
|
||||
token = secrets.token_urlsafe()
|
||||
return {"token": token, "user_id": user.id}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Generic, List, Optional
|
||||
from typing import Generic, Optional
|
||||
|
||||
import jwt
|
||||
|
||||
@@ -22,7 +22,7 @@ class JWTStrategy(Strategy[models.UP, models.ID], Generic[models.UP, models.ID])
|
||||
self,
|
||||
secret: SecretType,
|
||||
lifetime_seconds: Optional[int],
|
||||
token_audience: List[str] = ["fastapi-users:auth"],
|
||||
token_audience: list[str] = ["fastapi-users:auth"],
|
||||
algorithm: str = "HS256",
|
||||
public_key: Optional[SecretType] = None,
|
||||
):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Generic, Optional
|
||||
from typing import Any, Generic, Optional
|
||||
|
||||
from fastapi_users.models import ID, OAP, UOAP, UP
|
||||
from fastapi_users.types import DependencyCallable
|
||||
@@ -19,11 +19,11 @@ class BaseUserDatabase(Generic[UP, ID]):
|
||||
"""Get a single user by OAuth account id."""
|
||||
raise NotImplementedError()
|
||||
|
||||
async def create(self, create_dict: Dict[str, Any]) -> UP:
|
||||
async def create(self, create_dict: dict[str, Any]) -> UP:
|
||||
"""Create a user."""
|
||||
raise NotImplementedError()
|
||||
|
||||
async def update(self, user: UP, update_dict: Dict[str, Any]) -> UP:
|
||||
async def update(self, user: UP, update_dict: dict[str, Any]) -> UP:
|
||||
"""Update a user."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -32,7 +32,7 @@ class BaseUserDatabase(Generic[UP, ID]):
|
||||
raise NotImplementedError()
|
||||
|
||||
async def add_oauth_account(
|
||||
self: "BaseUserDatabase[UOAP, ID]", user: UOAP, create_dict: Dict[str, Any]
|
||||
self: "BaseUserDatabase[UOAP, ID]", user: UOAP, create_dict: dict[str, Any]
|
||||
) -> UOAP:
|
||||
"""Create an OAuth account and add it to the user."""
|
||||
raise NotImplementedError()
|
||||
@@ -41,7 +41,7 @@ class BaseUserDatabase(Generic[UP, ID]):
|
||||
self: "BaseUserDatabase[UOAP, ID]",
|
||||
user: UOAP,
|
||||
oauth_account: OAP,
|
||||
update_dict: Dict[str, Any],
|
||||
update_dict: dict[str, Any],
|
||||
) -> UOAP:
|
||||
"""Update an OAuth account on a user."""
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import Generic, Optional, Sequence, Type
|
||||
from collections.abc import Sequence
|
||||
from typing import Generic, Optional
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
@@ -20,7 +21,7 @@ try:
|
||||
from fastapi_users.router import get_oauth_router
|
||||
from fastapi_users.router.oauth import get_oauth_associate_router
|
||||
except ModuleNotFoundError: # pragma: no cover
|
||||
BaseOAuth2 = Type # type: ignore
|
||||
BaseOAuth2 = type # type: ignore
|
||||
|
||||
|
||||
class FastAPIUsers(Generic[models.UP, models.ID]):
|
||||
@@ -47,7 +48,7 @@ class FastAPIUsers(Generic[models.UP, models.ID]):
|
||||
self.current_user = self.authenticator.current_user
|
||||
|
||||
def get_register_router(
|
||||
self, user_schema: Type[schemas.U], user_create_schema: Type[schemas.UC]
|
||||
self, user_schema: type[schemas.U], user_create_schema: type[schemas.UC]
|
||||
) -> APIRouter:
|
||||
"""
|
||||
Return a router with a register route.
|
||||
@@ -59,7 +60,7 @@ class FastAPIUsers(Generic[models.UP, models.ID]):
|
||||
self.get_user_manager, user_schema, user_create_schema
|
||||
)
|
||||
|
||||
def get_verify_router(self, user_schema: Type[schemas.U]) -> APIRouter:
|
||||
def get_verify_router(self, user_schema: type[schemas.U]) -> APIRouter:
|
||||
"""
|
||||
Return a router with e-mail verification routes.
|
||||
|
||||
@@ -126,7 +127,7 @@ class FastAPIUsers(Generic[models.UP, models.ID]):
|
||||
def get_oauth_associate_router(
|
||||
self,
|
||||
oauth_client: BaseOAuth2,
|
||||
user_schema: Type[schemas.U],
|
||||
user_schema: type[schemas.U],
|
||||
state_secret: SecretType,
|
||||
redirect_url: Optional[str] = None,
|
||||
requires_verification: bool = False,
|
||||
@@ -154,8 +155,8 @@ class FastAPIUsers(Generic[models.UP, models.ID]):
|
||||
|
||||
def get_users_router(
|
||||
self,
|
||||
user_schema: Type[schemas.U],
|
||||
user_update_schema: Type[schemas.UU],
|
||||
user_schema: type[schemas.U],
|
||||
user_update_schema: type[schemas.UU],
|
||||
requires_verification: bool = False,
|
||||
) -> APIRouter:
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import jwt
|
||||
from pydantic import SecretStr
|
||||
@@ -30,9 +30,9 @@ def generate_jwt(
|
||||
def decode_jwt(
|
||||
encoded_jwt: str,
|
||||
secret: SecretType,
|
||||
audience: List[str],
|
||||
algorithms: List[str] = [JWT_ALGORITHM],
|
||||
) -> Dict[str, Any]:
|
||||
audience: list[str],
|
||||
algorithms: list[str] = [JWT_ALGORITHM],
|
||||
) -> dict[str, Any]:
|
||||
return jwt.decode(
|
||||
encoded_jwt,
|
||||
_get_secret_value(secret),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import uuid
|
||||
from typing import Any, Dict, Generic, Optional, Union
|
||||
from typing import Any, Generic, Optional, Union
|
||||
|
||||
import jwt
|
||||
from fastapi import Request, Response
|
||||
@@ -514,7 +514,7 @@ class BaseUserManager(Generic[models.UP, models.ID]):
|
||||
async def on_after_update(
|
||||
self,
|
||||
user: models.UP,
|
||||
update_dict: Dict[str, Any],
|
||||
update_dict: dict[str, Any],
|
||||
request: Optional[Request] = None,
|
||||
) -> None:
|
||||
"""
|
||||
@@ -662,7 +662,7 @@ class BaseUserManager(Generic[models.UP, models.ID]):
|
||||
|
||||
return user
|
||||
|
||||
async def _update(self, user: models.UP, update_dict: Dict[str, Any]) -> models.UP:
|
||||
async def _update(self, user: models.UP, update_dict: dict[str, Any]) -> models.UP:
|
||||
validated_update_dict = {}
|
||||
for field, value in update_dict.items():
|
||||
if field == "email" and value != user.email:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Generic, List, Optional, Protocol, TypeVar
|
||||
from typing import Generic, Optional, Protocol, TypeVar
|
||||
|
||||
ID = TypeVar("ID")
|
||||
|
||||
@@ -39,7 +39,7 @@ class UserOAuthProtocol(UserProtocol[ID], Generic[ID, OAP]):
|
||||
is_active: bool
|
||||
is_superuser: bool
|
||||
is_verified: bool
|
||||
oauth_accounts: List[OAP]
|
||||
oauth_accounts: list[OAP]
|
||||
|
||||
|
||||
UOAP = TypeVar("UOAP", bound=UserOAuthProtocol)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from typing import Any, Dict, Union
|
||||
from typing import Any, Union
|
||||
|
||||
OpenAPIResponseType = Dict[Union[int, str], Dict[str, Any]]
|
||||
OpenAPIResponseType = dict[Union[int, str], dict[str, Any]]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import secrets
|
||||
from typing import Optional, Protocol, Tuple, Union
|
||||
from typing import Optional, Protocol, Union
|
||||
|
||||
from pwdlib import PasswordHash
|
||||
from pwdlib.hashers.argon2 import Argon2Hasher
|
||||
@@ -9,7 +9,7 @@ from pwdlib.hashers.bcrypt import BcryptHasher
|
||||
class PasswordHelperProtocol(Protocol):
|
||||
def verify_and_update(
|
||||
self, plain_password: str, hashed_password: str
|
||||
) -> Tuple[bool, Union[str, None]]: ... # pragma: no cover
|
||||
) -> tuple[bool, Union[str, None]]: ... # pragma: no cover
|
||||
|
||||
def hash(self, password: str) -> str: ... # pragma: no cover
|
||||
|
||||
@@ -30,7 +30,7 @@ class PasswordHelper(PasswordHelperProtocol):
|
||||
|
||||
def verify_and_update(
|
||||
self, plain_password: str, hashed_password: str
|
||||
) -> Tuple[bool, Union[str, None]]:
|
||||
) -> tuple[bool, Union[str, None]]:
|
||||
return self.password_hash.verify_and_update(plain_password, hashed_password)
|
||||
|
||||
def hash(self, password: str) -> str:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Tuple
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
@@ -83,7 +81,7 @@ def get_auth_router(
|
||||
"/logout", name=f"auth:{backend.name}.logout", responses=logout_responses
|
||||
)
|
||||
async def logout(
|
||||
user_token: Tuple[models.UP, str] = Depends(get_current_user_token),
|
||||
user_token: tuple[models.UP, str] = Depends(get_current_user_token),
|
||||
strategy: Strategy[models.UP, models.ID] = Depends(backend.get_strategy),
|
||||
):
|
||||
user, token = user_token
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from enum import Enum
|
||||
from typing import Dict, Union
|
||||
from typing import Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ErrorModel(BaseModel):
|
||||
detail: Union[str, Dict[str, str]]
|
||||
detail: Union[str, dict[str, str]]
|
||||
|
||||
|
||||
class ErrorCodeReasonModel(BaseModel):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Dict, List, Optional, Tuple, Type
|
||||
from typing import Optional
|
||||
|
||||
import jwt
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
|
||||
@@ -21,7 +21,7 @@ class OAuth2AuthorizeResponse(BaseModel):
|
||||
|
||||
|
||||
def generate_state_token(
|
||||
data: Dict[str, str], secret: SecretType, lifetime_seconds: int = 3600
|
||||
data: dict[str, str], secret: SecretType, lifetime_seconds: int = 3600
|
||||
) -> str:
|
||||
data["aud"] = STATE_TOKEN_AUDIENCE
|
||||
return generate_jwt(data, secret, lifetime_seconds)
|
||||
@@ -57,14 +57,14 @@ def get_oauth_router(
|
||||
response_model=OAuth2AuthorizeResponse,
|
||||
)
|
||||
async def authorize(
|
||||
request: Request, scopes: List[str] = Query(None)
|
||||
request: Request, scopes: list[str] = Query(None)
|
||||
) -> OAuth2AuthorizeResponse:
|
||||
if redirect_url is not None:
|
||||
authorize_redirect_url = redirect_url
|
||||
else:
|
||||
authorize_redirect_url = str(request.url_for(callback_route_name))
|
||||
|
||||
state_data: Dict[str, str] = {}
|
||||
state_data: dict[str, str] = {}
|
||||
state = generate_state_token(state_data, state_secret)
|
||||
authorization_url = await oauth_client.get_authorization_url(
|
||||
authorize_redirect_url,
|
||||
@@ -100,7 +100,7 @@ def get_oauth_router(
|
||||
)
|
||||
async def callback(
|
||||
request: Request,
|
||||
access_token_state: Tuple[OAuth2Token, str] = Depends(
|
||||
access_token_state: tuple[OAuth2Token, str] = Depends(
|
||||
oauth2_authorize_callback
|
||||
),
|
||||
user_manager: BaseUserManager[models.UP, models.ID] = Depends(get_user_manager),
|
||||
@@ -158,7 +158,7 @@ def get_oauth_associate_router(
|
||||
oauth_client: BaseOAuth2,
|
||||
authenticator: Authenticator[models.UP, models.ID],
|
||||
get_user_manager: UserManagerDependency[models.UP, models.ID],
|
||||
user_schema: Type[schemas.U],
|
||||
user_schema: type[schemas.U],
|
||||
state_secret: SecretType,
|
||||
redirect_url: Optional[str] = None,
|
||||
requires_verification: bool = False,
|
||||
@@ -190,7 +190,7 @@ def get_oauth_associate_router(
|
||||
)
|
||||
async def authorize(
|
||||
request: Request,
|
||||
scopes: List[str] = Query(None),
|
||||
scopes: list[str] = Query(None),
|
||||
user: models.UP = Depends(get_current_active_user),
|
||||
) -> OAuth2AuthorizeResponse:
|
||||
if redirect_url is not None:
|
||||
@@ -198,7 +198,7 @@ def get_oauth_associate_router(
|
||||
else:
|
||||
authorize_redirect_url = str(request.url_for(callback_route_name))
|
||||
|
||||
state_data: Dict[str, str] = {"sub": str(user.id)}
|
||||
state_data: dict[str, str] = {"sub": str(user.id)}
|
||||
state = generate_state_token(state_data, state_secret)
|
||||
authorization_url = await oauth_client.get_authorization_url(
|
||||
authorize_redirect_url,
|
||||
@@ -232,7 +232,7 @@ def get_oauth_associate_router(
|
||||
async def callback(
|
||||
request: Request,
|
||||
user: models.UP = Depends(get_current_active_user),
|
||||
access_token_state: Tuple[OAuth2Token, str] = Depends(
|
||||
access_token_state: tuple[OAuth2Token, str] = Depends(
|
||||
oauth2_authorize_callback
|
||||
),
|
||||
user_manager: BaseUserManager[models.UP, models.ID] = Depends(get_user_manager),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
|
||||
from fastapi_users import exceptions, models, schemas
|
||||
@@ -9,8 +7,8 @@ from fastapi_users.router.common import ErrorCode, ErrorModel
|
||||
|
||||
def get_register_router(
|
||||
get_user_manager: UserManagerDependency[models.UP, models.ID],
|
||||
user_schema: Type[schemas.U],
|
||||
user_create_schema: Type[schemas.UC],
|
||||
user_schema: type[schemas.U],
|
||||
user_create_schema: type[schemas.UC],
|
||||
) -> APIRouter:
|
||||
"""Generate a router with the register route."""
|
||||
router = APIRouter()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
|
||||
|
||||
from fastapi_users import exceptions, models, schemas
|
||||
@@ -10,8 +8,8 @@ from fastapi_users.router.common import ErrorCode, ErrorModel
|
||||
|
||||
def get_users_router(
|
||||
get_user_manager: UserManagerDependency[models.UP, models.ID],
|
||||
user_schema: Type[schemas.U],
|
||||
user_update_schema: Type[schemas.UU],
|
||||
user_schema: type[schemas.U],
|
||||
user_update_schema: type[schemas.UU],
|
||||
authenticator: Authenticator[models.UP, models.ID],
|
||||
requires_verification: bool = False,
|
||||
) -> APIRouter:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, Request, status
|
||||
from pydantic import EmailStr
|
||||
|
||||
@@ -10,7 +8,7 @@ from fastapi_users.router.common import ErrorCode, ErrorModel
|
||||
|
||||
def get_verify_router(
|
||||
get_user_manager: UserManagerDependency[models.UP, models.ID],
|
||||
user_schema: Type[schemas.U],
|
||||
user_schema: type[schemas.U],
|
||||
):
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Generic, List, Optional, Type, TypeVar
|
||||
from typing import Any, Generic, Optional, TypeVar
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, EmailStr
|
||||
from pydantic.version import VERSION as PYDANTIC_VERSION
|
||||
@@ -11,18 +11,18 @@ SCHEMA = TypeVar("SCHEMA", bound=BaseModel)
|
||||
|
||||
if PYDANTIC_V2: # pragma: no cover
|
||||
|
||||
def model_dump(model: BaseModel, *args, **kwargs) -> Dict[str, Any]:
|
||||
def model_dump(model: BaseModel, *args, **kwargs) -> dict[str, Any]:
|
||||
return model.model_dump(*args, **kwargs) # type: ignore
|
||||
|
||||
def model_validate(schema: Type[SCHEMA], obj: Any, *args, **kwargs) -> SCHEMA:
|
||||
def model_validate(schema: type[SCHEMA], obj: Any, *args, **kwargs) -> SCHEMA:
|
||||
return schema.model_validate(obj, *args, **kwargs) # type: ignore
|
||||
|
||||
else: # pragma: no cover # type: ignore
|
||||
|
||||
def model_dump(model: BaseModel, *args, **kwargs) -> Dict[str, Any]:
|
||||
def model_dump(model: BaseModel, *args, **kwargs) -> dict[str, Any]:
|
||||
return model.dict(*args, **kwargs) # type: ignore
|
||||
|
||||
def model_validate(schema: Type[SCHEMA], obj: Any, *args, **kwargs) -> SCHEMA:
|
||||
def model_validate(schema: type[SCHEMA], obj: Any, *args, **kwargs) -> SCHEMA:
|
||||
return schema.from_orm(obj) # type: ignore
|
||||
|
||||
|
||||
@@ -104,4 +104,4 @@ class BaseOAuthAccount(BaseModel, Generic[models.ID]):
|
||||
class BaseOAuthAccountMixin(BaseModel):
|
||||
"""Adds OAuth accounts list to a User model."""
|
||||
|
||||
oauth_accounts: List[BaseOAuthAccount] = []
|
||||
oauth_accounts: list[BaseOAuthAccount] = []
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
from typing import (
|
||||
AsyncGenerator,
|
||||
AsyncIterator,
|
||||
Callable,
|
||||
Coroutine,
|
||||
Generator,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
from collections.abc import AsyncGenerator, AsyncIterator, Coroutine, Generator
|
||||
from typing import Callable, TypeVar, Union
|
||||
|
||||
RETURN_TYPE = TypeVar("RETURN_TYPE")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user