update to python3.10 (#29)

This commit is contained in:
dylan
2023-05-03 17:10:55 +08:00
committed by GitHub
parent 4e6284eafe
commit 64f2a13e37
14 changed files with 46 additions and 44 deletions

View File

@ -18,10 +18,10 @@ repos:
rev: 23.3.0 rev: 23.3.0
hooks: hooks:
- id: black - id: black
language_version: python3.8 language_version: python3.10
args: args:
- '--skip-string-normalization' - '--skip-string-normalization'
- '--line-length' - '--line-length'
- '120' - '120'
- '--target-version' - '--target-version'
- 'py38' - 'py310'

View File

@ -9,11 +9,14 @@ select = [
"PGH004", "PGH004",
"PLE1142", "PLE1142",
"RUF100", "RUF100",
"I002",
"F404",
"TCH",
"UP007"
] ]
ignore = ["F401"]
line-length = 120 line-length = 120
format = "grouped" format = "grouped"
target-version = "py38" target-version = "py310"
cache-dir = "./.ruff_cache" cache-dir = "./.ruff_cache"
[flake8-pytest-style] [flake8-pytest-style]
@ -34,3 +37,8 @@ ignore-variadic-names = true
[isort] [isort]
lines-between-types = 1 lines-between-types = 1
order-by-type = true order-by-type = true
[per-file-ignores]
"backend/app/api/v1/*.py" = ["TCH"]
"backend/app/models/*.py" = ["TCH003"]
"backend/app/**/__init__.py" = ["F401"]

View File

@ -5,6 +5,8 @@ This is a base project of the FastAPI framework.
Its purpose is to allow you to develop your project directly with it Its purpose is to allow you to develop your project directly with it
as your base project as your base project
Support python3.10 and above
## Skill ## Skill
- [x] FastAPI - [x] FastAPI

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Union from typing import Any
from fastapi import Depends from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
@ -42,7 +42,7 @@ def password_verify(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password) return pwd_context.verify(plain_password, hashed_password)
def create_access_token(data: Union[int, Any], expires_delta: Union[timedelta, None] = None) -> str: def create_access_token(data: int | Any, expires_delta: timedelta | None = None) -> str:
""" """
Generate encryption token Generate encryption token

View File

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
import math import math
from typing import TypeVar, Generic, Sequence, Dict, Union from typing import TypeVar, Generic, Sequence, Dict
from fastapi import Query from fastapi import Query
from fastapi_pagination.bases import AbstractPage, AbstractParams, RawParams from fastapi_pagination.bases import AbstractPage, AbstractParams, RawParams
@ -35,7 +35,7 @@ class Page(AbstractPage[T], Generic[T]):
page: int # 第n页 page: int # 第n页
size: int # 每页数量 size: int # 每页数量
total_pages: int # 总页数 total_pages: int # 总页数
links: Dict[str, Union[str, None]] # 跳转链接 links: Dict[str, str | None] # 跳转链接
__params_type__ = Params # 使用自定义的Params __params_type__ = Params # 使用自定义的Params

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime from datetime import datetime
from typing import Optional, Any, Union, Set, Dict from typing import Any, Union, Set, Dict
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from pydantic import validate_arguments, BaseModel from pydantic import validate_arguments, BaseModel
_JsonEncoder = Union[Set[Union[int, str]], Dict[Union[int, str], Any]] _JsonEncoder = Union[Set[int | str], Dict[int | str, Any]]
__all__ = ['ResponseModel', 'response_base'] __all__ = ['ResponseModel', 'response_base']
@ -18,7 +18,7 @@ class ResponseModel(BaseModel):
code: int = 200 code: int = 200
msg: str = 'Success' msg: str = 'Success'
data: Optional[Any] = None data: Any | None = None
class Config: class Config:
json_encoders = {datetime: lambda x: x.strftime('%Y-%m-%d %H:%M:%S')} json_encoders = {datetime: lambda x: x.strftime('%Y-%m-%d %H:%M:%S')}
@ -31,9 +31,7 @@ class ResponseBase:
@staticmethod @staticmethod
@validate_arguments @validate_arguments
def success( def success(*, code: int = 200, msg: str = 'Success', data: Any | None = None, exclude: _JsonEncoder | None = None):
*, code: int = 200, msg: str = 'Success', data: Optional[Any] = None, exclude: Optional[_JsonEncoder] = None
):
""" """
请求成功返回通用方法 请求成功返回通用方法
@ -48,13 +46,13 @@ class ResponseBase:
@staticmethod @staticmethod
@validate_arguments @validate_arguments
def fail(*, code: int = 400, msg: str = 'Bad Request', data: Any = None, exclude: Optional[_JsonEncoder] = None): def fail(*, code: int = 400, msg: str = 'Bad Request', data: Any = None, exclude: _JsonEncoder | None = None):
data = data if data is None else ResponseBase.__encode_json(data) data = data if data is None else ResponseBase.__encode_json(data)
return ResponseModel(code=code, msg=msg, data=data).dict(exclude={'data': exclude}) return ResponseModel(code=code, msg=msg, data=data).dict(exclude={'data': exclude})
@staticmethod @staticmethod
@validate_arguments @validate_arguments
def response_200(*, msg: str = 'Success', data: Optional[Any] = None, exclude: Optional[_JsonEncoder] = None): def response_200(*, msg: str = 'Success', data: Any | None = None, exclude: _JsonEncoder | None = None):
data = data if data is None else ResponseBase.__encode_json(data) data = data if data is None else ResponseBase.__encode_json(data)
return ResponseModel(code=200, msg=msg, data=data).dict(exclude={'data': exclude}) return ResponseModel(code=200, msg=msg, data=data).dict(exclude={'data': exclude})

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from functools import lru_cache from functools import lru_cache
from typing import Optional
from pydantic import BaseSettings, root_validator from pydantic import BaseSettings, root_validator
@ -35,9 +34,9 @@ class Settings(BaseSettings):
TITLE: str = 'FastAPI' TITLE: str = 'FastAPI'
VERSION: str = '0.0.1' VERSION: str = '0.0.1'
DESCRIPTION: str = 'FastAPI Best Architecture' DESCRIPTION: str = 'FastAPI Best Architecture'
DOCS_URL: Optional[str] = '/v1/docs' DOCS_URL: str | None = '/v1/docs'
REDOCS_URL: Optional[str] = '/v1/redocs' REDOCS_URL: str | None = '/v1/redocs'
OPENAPI_URL: Optional[str] = '/v1/openapi' OPENAPI_URL: str | None = '/v1/openapi'
@root_validator @root_validator
def validator_api_url(cls, values): def validator_api_url(cls, values):

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Any, Dict, Generic, Type, TypeVar, Union, Optional, NoReturn from typing import Any, Dict, Generic, Type, TypeVar, NoReturn
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy import select, update, delete from sqlalchemy import select, update, delete
@ -17,7 +17,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
def __init__(self, model: Type[ModelType]): def __init__(self, model: Type[ModelType]):
self.model = model self.model = model
async def get(self, db: AsyncSession, pk: int) -> Optional[ModelType]: async def get(self, db: AsyncSession, pk: int) -> ModelType | None:
""" """
通过主键 id 获取一条数据 通过主键 id 获取一条数据
@ -28,7 +28,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
model = await db.execute(select(self.model).where(self.model.id == pk)) model = await db.execute(select(self.model).where(self.model.id == pk))
return model.scalars().first() return model.scalars().first()
async def create(self, db: AsyncSession, obj_in: CreateSchemaType, user_id: Optional[int] = None) -> NoReturn: async def create(self, db: AsyncSession, obj_in: CreateSchemaType, user_id: int | None = None) -> NoReturn:
""" """
新增一条数据 新增一条数据
@ -44,7 +44,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
db.add(db_obj) db.add(db_obj)
async def update( async def update(
self, db: AsyncSession, pk: int, obj_in: Union[UpdateSchemaType, Dict[str, Any]], user_id: Optional[int] = None self, db: AsyncSession, pk: int, obj_in: UpdateSchemaType | Dict[str, Any], user_id: int | None = None
) -> int: ) -> int:
""" """
通过主键 id 更新一条数据 通过主键 id 更新一条数据

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Optional, NoReturn from typing import NoReturn
from sqlalchemy import func, select, update, desc from sqlalchemy import func, select, update, desc
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@ -13,10 +13,10 @@ from backend.app.schemas.user import CreateUser, UpdateUser, Avatar
class CRUDUser(CRUDBase[User, CreateUser, UpdateUser]): class CRUDUser(CRUDBase[User, CreateUser, UpdateUser]):
async def get_user_by_id(self, db: AsyncSession, user_id: int) -> Optional[User]: async def get_user_by_id(self, db: AsyncSession, user_id: int) -> User | None:
return await self.get(db, user_id) return await self.get(db, user_id)
async def get_user_by_username(self, db: AsyncSession, username: str) -> Optional[User]: async def get_user_by_username(self, db: AsyncSession, username: str) -> User | None:
user = await db.execute(select(self.model).where(self.model.username == username)) user = await db.execute(select(self.model).where(self.model.username == username))
return user.scalars().first() return user.scalars().first()

View File

@ -2,7 +2,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import Optional
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, declared_attr, MappedAsDataclass from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, declared_attr, MappedAsDataclass
@ -24,9 +23,9 @@ class _BaseMixin(MappedAsDataclass):
""" """
create_user: Mapped[int] = mapped_column(sort_order=9999, comment='创建者') create_user: Mapped[int] = mapped_column(sort_order=9999, comment='创建者')
update_user: Mapped[Optional[int]] = mapped_column(init=False, default=None, sort_order=9999, comment='修改者') update_user: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=9999, comment='修改者')
created_time: Mapped[datetime] = mapped_column(init=False, default=func.now(), sort_order=9999, comment='创建时间') created_time: Mapped[datetime] = mapped_column(init=False, default=func.now(), sort_order=9999, comment='创建时间')
updated_time: Mapped[Optional[datetime]] = mapped_column( updated_time: Mapped[datetime | None] = mapped_column(
init=False, onupdate=func.now(), sort_order=9999, comment='更新时间' init=False, onupdate=func.now(), sort_order=9999, comment='更新时间'
) )

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime from datetime import datetime
from typing import Optional
from sqlalchemy import func, String from sqlalchemy import func, String
from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.orm import Mapped, mapped_column
@ -21,7 +20,7 @@ class User(DataClassBase):
email: Mapped[str] = mapped_column(String(50), unique=True, index=True, comment='邮箱') email: Mapped[str] = mapped_column(String(50), unique=True, index=True, comment='邮箱')
is_superuser: Mapped[bool] = mapped_column(default=False, comment='超级权限') is_superuser: Mapped[bool] = mapped_column(default=False, comment='超级权限')
is_active: Mapped[bool] = mapped_column(default=True, comment='用户账号状态') is_active: Mapped[bool] = mapped_column(default=True, comment='用户账号状态')
avatar: Mapped[Optional[str]] = mapped_column(String(255), default=None, comment='头像') avatar: Mapped[str | None] = mapped_column(String(255), default=None, comment='头像')
mobile_number: Mapped[Optional[str]] = mapped_column(String(11), default=None, comment='手机号') mobile_number: Mapped[str | None] = mapped_column(String(11), default=None, comment='手机号')
time_joined: Mapped[datetime] = mapped_column(init=False, default=func.now(), comment='注册时间') time_joined: Mapped[datetime] = mapped_column(init=False, default=func.now(), comment='注册时间')
last_login: Mapped[Optional[datetime]] = mapped_column(init=False, onupdate=func.now(), comment='上次登录') last_login: Mapped[datetime | None] = mapped_column(init=False, onupdate=func.now(), comment='上次登录')

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from typing import Optional
from pydantic import BaseModel from pydantic import BaseModel
@ -10,4 +9,4 @@ class Token(BaseModel):
msg: str = 'Success' msg: str = 'Success'
access_token: str access_token: str
token_type: str = 'Bearer' token_type: str = 'Bearer'
is_superuser: Optional[bool] = None is_superuser: bool | None = None

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field, HttpUrl from pydantic import BaseModel, Field, HttpUrl
@ -18,7 +17,7 @@ class CreateUser(Auth):
class UpdateUser(BaseModel): class UpdateUser(BaseModel):
username: str username: str
email: str email: str
mobile_number: Optional[str] = None mobile_number: str | None = None
class Avatar(BaseModel): class Avatar(BaseModel):
@ -28,9 +27,9 @@ class Avatar(BaseModel):
class GetUserInfo(UpdateUser): class GetUserInfo(UpdateUser):
id: int id: int
uid: str uid: str
avatar: Optional[str] = None avatar: str | None = None
time_joined: datetime.datetime = None time_joined: datetime.datetime = None
last_login: Optional[datetime.datetime] = None last_login: datetime.datetime | None = None
is_superuser: bool is_superuser: bool
is_active: bool is_active: bool

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from functools import lru_cache from functools import lru_cache
from typing import Optional
from pydantic import BaseSettings from pydantic import BaseSettings
@ -11,9 +10,9 @@ class Settings(BaseSettings):
TITLE: str = 'FastAPI' TITLE: str = 'FastAPI'
VERSION: str = 'v0.0.1' VERSION: str = 'v0.0.1'
DESCRIPTION: str = 'FastAPI Best Architecture' DESCRIPTION: str = 'FastAPI Best Architecture'
DOCS_URL: Optional[str] = '/v1/docs' DOCS_URL: str | None = '/v1/docs'
REDOCS_URL: Optional[str] = None REDOCS_URL: str | None = None
OPENAPI_URL: Optional[str] = '/v1/openapi' OPENAPI_URL: str | None = '/v1/openapi'
# Static Server # Static Server
STATIC_FILES: bool = False STATIC_FILES: bool = False