diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 58de18a8..b1ec64c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,10 +18,10 @@ repos: rev: 23.3.0 hooks: - id: black - language_version: python3.8 + language_version: python3.10 args: - '--skip-string-normalization' - '--line-length' - '120' - '--target-version' - - 'py38' + - 'py310' diff --git a/.ruff.toml b/.ruff.toml index b47ea802..7047c408 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -9,6 +9,10 @@ select = [ "PGH004", "PLE1142", "RUF100", + "I002", + "F404", + "TCH", + "UP007" ] ignore = ["F401"] line-length = 120 @@ -34,3 +38,8 @@ ignore-variadic-names = true [isort] lines-between-types = 1 order-by-type = true +required-imports = ["from __future__ import annotations"] + +[per-file-ignores] +"backend/app/api/v1/*.py" = ["TCH"] +"backend/app/models/*.py" = ["TCH003"] diff --git a/backend/app/alembic/env.py b/backend/app/alembic/env.py index ab44aefd..3987ff99 100644 --- a/backend/app/alembic/env.py +++ b/backend/app/alembic/env.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from __future__ import annotations import asyncio import os import sys diff --git a/backend/app/api/jwt.py b/backend/app/api/jwt.py index 90330918..652b7aae 100644 --- a/backend/app/api/jwt.py +++ b/backend/app/api/jwt.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + from datetime import datetime, timedelta -from typing import Any, Union +from typing import Any from fastapi import Depends from fastapi.security import OAuth2PasswordBearer @@ -13,7 +15,7 @@ from backend.app.common.exception.errors import AuthorizationError, TokenError from backend.app.core.conf import settings from backend.app.crud.crud_user import UserDao -from backend.app.database.db_mysql import CurrentSession +from backend.app.database.db_mysql import CurrentSession # noqa: TCH001 from backend.app.models import User pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto') @@ -42,7 +44,7 @@ def password_verify(plain_password: str, hashed_password: str) -> bool: 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 diff --git a/backend/app/api/routers.py b/backend/app/api/routers.py index 56375567..b000598a 100644 --- a/backend/app/api/routers.py +++ b/backend/app/api/routers.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from fastapi import APIRouter from backend.app.api.v1.auth import router as auth_router diff --git a/backend/app/api/service/user_service.py b/backend/app/api/service/user_service.py index acf7c590..f2616ea2 100644 --- a/backend/app/api/service/user_service.py +++ b/backend/app/api/service/user_service.py @@ -1,17 +1,23 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + +from typing import TYPE_CHECKING + from email_validator import validate_email, EmailNotValidError -from fastapi.security import OAuth2PasswordRequestForm from fastapi_pagination.ext.sqlalchemy import paginate from backend.app.api import jwt from backend.app.common.exception import errors from backend.app.crud.crud_user import UserDao from backend.app.database.db_mysql import async_db_session -from backend.app.models import User -from backend.app.schemas.user import CreateUser, ResetPassword, UpdateUser, Avatar from backend.app.utils import re_verify +if TYPE_CHECKING: + from fastapi.security import OAuth2PasswordRequestForm + from backend.app.models import User + from backend.app.schemas.user import CreateUser, ResetPassword, UpdateUser, Avatar + class UserService: @staticmethod diff --git a/backend/app/api/v1/auth/__init__.py b/backend/app/api/v1/auth/__init__.py index caa19ead..812f590c 100644 --- a/backend/app/api/v1/auth/__init__.py +++ b/backend/app/api/v1/auth/__init__.py @@ -1,3 +1,4 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from backend.app.api.v1.auth.user import router diff --git a/backend/app/api/v1/auth/user.py b/backend/app/api/v1/auth/user.py index a1c12c00..eebca46f 100644 --- a/backend/app/api/v1/auth/user.py +++ b/backend/app/api/v1/auth/user.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + from fastapi import APIRouter, Depends from fastapi.security import OAuth2PasswordRequestForm diff --git a/backend/app/api/v1/task_demo.py b/backend/app/api/v1/task_demo.py index d6ceb14e..32823f62 100644 --- a/backend/app/api/v1/task_demo.py +++ b/backend/app/api/v1/task_demo.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + import datetime +from typing import Annotated from fastapi import APIRouter, Query -from typing_extensions import Annotated from backend.app.common.task import scheduler diff --git a/backend/app/common/enums.py b/backend/app/common/enums.py index cc1d145c..12507dce 100644 --- a/backend/app/common/enums.py +++ b/backend/app/common/enums.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from enum import Enum diff --git a/backend/app/common/exception/errors.py b/backend/app/common/exception/errors.py index a5f5ed8f..4dd07e48 100644 --- a/backend/app/common/exception/errors.py +++ b/backend/app/common/exception/errors.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Any +from __future__ import annotations +from typing import Any, TYPE_CHECKING from fastapi import HTTPException -from backend.app.common.response.response_code import CodeEnum +if TYPE_CHECKING: + from backend.app.common.response.response_code import CodeEnum class BaseExceptionMixin(Exception): diff --git a/backend/app/common/exception/exception_handler.py b/backend/app/common/exception/exception_handler.py index 8a49b17a..883c7f8b 100644 --- a/backend/app/common/exception/exception_handler.py +++ b/backend/app/common/exception/exception_handler.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import json +from typing import TYPE_CHECKING -from fastapi import FastAPI, Request from fastapi.exceptions import RequestValidationError, HTTPException from pydantic import ValidationError from starlette.responses import JSONResponse @@ -12,6 +13,9 @@ from backend.app.common.response.response_schema import response_base from backend.app.core.conf import settings +if TYPE_CHECKING: + from fastapi import FastAPI, Request + def _get_exception_code(status_code): """ diff --git a/backend/app/common/log.py b/backend/app/common/log.py index 30d1a7f5..1446f2f8 100644 --- a/backend/app/common/log.py +++ b/backend/app/common/log.py @@ -3,13 +3,16 @@ from __future__ import annotations import os +from typing import TYPE_CHECKING -import loguru from loguru import logger from backend.app.core import path_conf from backend.app.core.conf import settings +if TYPE_CHECKING: + import loguru + class Logger: @staticmethod diff --git a/backend/app/common/pagination.py b/backend/app/common/pagination.py index e195d570..b428c674 100644 --- a/backend/app/common/pagination.py +++ b/backend/app/common/pagination.py @@ -35,7 +35,7 @@ class Page(AbstractPage[T], Generic[T]): page: int # 第n页 size: int # 每页数量 total_pages: int # 总页数 - links: Dict[str, Union[str, None]] # 跳转链接 + links: Dict[str, str | None] # 跳转链接 __params_type__ = Params # 使用自定义的Params diff --git a/backend/app/common/redis.py b/backend/app/common/redis.py index f4e035f5..dde1ee08 100644 --- a/backend/app/common/redis.py +++ b/backend/app/common/redis.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import sys from aioredis import Redis, TimeoutError, AuthenticationError diff --git a/backend/app/common/response/response_code.py b/backend/app/common/response/response_code.py index a55dc15a..5253394b 100644 --- a/backend/app/common/response/response_code.py +++ b/backend/app/common/response/response_code.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from enum import Enum diff --git a/backend/app/common/response/response_schema.py b/backend/app/common/response/response_schema.py index e2909d8f..c7d13887 100644 --- a/backend/app/common/response/response_schema.py +++ b/backend/app/common/response/response_schema.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from datetime import datetime from typing import Optional, Any, Union, Set, Dict @@ -18,7 +19,7 @@ class ResponseModel(BaseModel): code: int = 200 msg: str = 'Success' - data: Optional[Any] = None + data: Any | None = None class Config: json_encoders = {datetime: lambda x: x.strftime('%Y-%m-%d %H:%M:%S')} @@ -31,9 +32,7 @@ def __encode_json(data: Any): @staticmethod @validate_arguments - def success( - *, code: int = 200, msg: str = 'Success', data: Optional[Any] = None, exclude: Optional[_JsonEncoder] = None - ): + def success(*, code: int = 200, msg: str = 'Success', data: Any | None = None, exclude: _JsonEncoder | None = None): """ 请求成功返回通用方法 @@ -48,13 +47,13 @@ def success( @staticmethod @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) return ResponseModel(code=code, msg=msg, data=data).dict(exclude={'data': exclude}) @staticmethod @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) return ResponseModel(code=200, msg=msg, data=data).dict(exclude={'data': exclude}) diff --git a/backend/app/common/task.py b/backend/app/common/task.py index 5a1888b6..5cd9d2f8 100644 --- a/backend/app/common/task.py +++ b/backend/app/common/task.py @@ -1,5 +1,6 @@ # !/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import tzlocal from apscheduler.executors.asyncio import AsyncIOExecutor from apscheduler.jobstores.redis import RedisJobStore diff --git a/backend/app/core/conf.py b/backend/app/core/conf.py index 59f53635..d7406632 100644 --- a/backend/app/core/conf.py +++ b/backend/app/core/conf.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + from functools import lru_cache -from typing import Optional from pydantic import BaseSettings, root_validator @@ -35,9 +36,9 @@ class Settings(BaseSettings): TITLE: str = 'FastAPI' VERSION: str = '0.0.1' DESCRIPTION: str = 'FastAPI Best Architecture' - DOCS_URL: Optional[str] = '/v1/docs' - REDOCS_URL: Optional[str] = '/v1/redocs' - OPENAPI_URL: Optional[str] = '/v1/openapi' + DOCS_URL: str | None = '/v1/docs' + REDOCS_URL: str | None = '/v1/redocs' + OPENAPI_URL: str | None = '/v1/openapi' @root_validator def validator_api_url(cls, values): diff --git a/backend/app/core/path_conf.py b/backend/app/core/path_conf.py index 343ab987..13b30aa9 100644 --- a/backend/app/core/path_conf.py +++ b/backend/app/core/path_conf.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import os from pathlib import Path diff --git a/backend/app/core/registrar.py b/backend/app/core/registrar.py index 2aa96477..f6a49e77 100644 --- a/backend/app/core/registrar.py +++ b/backend/app/core/registrar.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from contextlib import asynccontextmanager from fastapi import FastAPI diff --git a/backend/app/crud/base.py b/backend/app/crud/base.py index c22a51ef..88a47140 100644 --- a/backend/app/crud/base.py +++ b/backend/app/crud/base.py @@ -1,13 +1,17 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Any, Dict, Generic, Type, TypeVar, Union, Optional, NoReturn +from __future__ import annotations + +from typing import Any, Dict, Generic, Type, TypeVar, NoReturn, TYPE_CHECKING from pydantic import BaseModel from sqlalchemy import select, update, delete -from sqlalchemy.ext.asyncio import AsyncSession from backend.app.database.base_class import MappedBase +if TYPE_CHECKING: + from sqlalchemy.ext.asyncio import AsyncSession + ModelType = TypeVar('ModelType', bound=MappedBase) CreateSchemaType = TypeVar('CreateSchemaType', bound=BaseModel) UpdateSchemaType = TypeVar('UpdateSchemaType', bound=BaseModel) @@ -17,7 +21,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): def __init__(self, model: Type[ModelType]): self.model = model - async def get(self, db: AsyncSession, pk: int) -> Optional[ModelType]: + async def get(self, db: AsyncSession, pk: int) -> ModelType | None: """ 通过主键 id 获取一条数据 @@ -28,7 +32,7 @@ async def get(self, db: AsyncSession, pk: int) -> Optional[ModelType]: model = await db.execute(select(self.model).where(self.model.id == pk)) 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 +48,7 @@ async def create(self, db: AsyncSession, obj_in: CreateSchemaType, user_id: Opti db.add(db_obj) 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: """ 通过主键 id 更新一条数据 diff --git a/backend/app/crud/crud_user.py b/backend/app/crud/crud_user.py index 7138fab4..5b6cc314 100644 --- a/backend/app/crud/crud_user.py +++ b/backend/app/crud/crud_user.py @@ -1,22 +1,25 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Optional, NoReturn +from __future__ import annotations +from typing import Optional, NoReturn, TYPE_CHECKING from sqlalchemy import func, select, update, desc -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.sql import Select from backend.app.api import jwt from backend.app.crud.base import CRUDBase from backend.app.models import User from backend.app.schemas.user import CreateUser, UpdateUser, Avatar +if TYPE_CHECKING: + from sqlalchemy.ext.asyncio import AsyncSession + from sqlalchemy.sql import Select + 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) - 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)) return user.scalars().first() diff --git a/backend/app/database/base_class.py b/backend/app/database/base_class.py index 280c7948..a874e0fa 100644 --- a/backend/app/database/base_class.py +++ b/backend/app/database/base_class.py @@ -1,13 +1,17 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + import uuid -from datetime import datetime -from typing import Optional +from typing import TYPE_CHECKING from sqlalchemy import func from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, declared_attr, MappedAsDataclass from typing_extensions import Annotated +if TYPE_CHECKING: + import datetime + # 通用 Mapped 类型主键, 需手动添加,参考以下使用方式 # MappedBase -> id: Mapped[id_key] # DataClassBase && Base -> id: Mapped[id_key] = mapped_column(init=False) @@ -24,9 +28,9 @@ class _BaseMixin(MappedAsDataclass): """ 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='创建时间') - updated_time: Mapped[Optional[datetime]] = mapped_column( + updated_time: Mapped[datetime | None] = mapped_column( init=False, onupdate=func.now(), sort_order=9999, comment='更新时间' ) diff --git a/backend/app/database/db_mysql.py b/backend/app/database/db_mysql.py index 31bfefba..a4c282af 100644 --- a/backend/app/database/db_mysql.py +++ b/backend/app/database/db_mysql.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import sys from fastapi import Depends diff --git a/backend/app/init_test_data.py b/backend/app/init_test_data.py index 34d1f498..4db6b58a 100644 --- a/backend/app/init_test_data.py +++ b/backend/app/init_test_data.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import asyncio from email_validator import EmailNotValidError, validate_email diff --git a/backend/app/main.py b/backend/app/main.py index bb831790..232a29bb 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import uvicorn from path import Path diff --git a/backend/app/middleware/access_middle.py b/backend/app/middleware/access_middle.py index 0682d6a7..fcf908ee 100644 --- a/backend/app/middleware/access_middle.py +++ b/backend/app/middleware/access_middle.py @@ -1,12 +1,16 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from datetime import datetime +from typing import TYPE_CHECKING -from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware from backend.app.common.log import log +if TYPE_CHECKING: + from fastapi import Request, Response + class AccessMiddleware(BaseHTTPMiddleware): """ diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index eac378ee..8cf0139d 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -4,5 +4,6 @@ # 导入所有模型,并将 Base 放在最前面, 以便 Base 拥有它们 # imported by Alembic """ +from __future__ import annotations from backend.app.database.base_class import MappedBase from backend.app.models.user import User diff --git a/backend/app/models/user.py b/backend/app/models/user.py index f2ceca7d..cc6a88e1 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations + from datetime import datetime -from typing import Optional from sqlalchemy import func, String from sqlalchemy.orm import Mapped, mapped_column @@ -21,7 +22,7 @@ class User(DataClassBase): email: Mapped[str] = mapped_column(String(50), unique=True, index=True, comment='邮箱') is_superuser: Mapped[bool] = mapped_column(default=False, comment='超级权限') is_active: Mapped[bool] = mapped_column(default=True, comment='用户账号状态') - avatar: Mapped[Optional[str]] = mapped_column(String(255), default=None, comment='头像') - mobile_number: Mapped[Optional[str]] = mapped_column(String(11), default=None, comment='手机号') + avatar: Mapped[str | None] = mapped_column(String(255), 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='注册时间') - 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='上次登录') diff --git a/backend/app/schemas/token.py b/backend/app/schemas/token.py index 088e432e..b5e30a53 100644 --- a/backend/app/schemas/token.py +++ b/backend/app/schemas/token.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Optional +from __future__ import annotations from pydantic import BaseModel @@ -10,4 +10,4 @@ class Token(BaseModel): msg: str = 'Success' access_token: str token_type: str = 'Bearer' - is_superuser: Optional[bool] = None + is_superuser: bool | None = None diff --git a/backend/app/schemas/user.py b/backend/app/schemas/user.py index 18503bc6..18220708 100644 --- a/backend/app/schemas/user.py +++ b/backend/app/schemas/user.py @@ -1,10 +1,14 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import datetime -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING from pydantic import BaseModel, Field, HttpUrl +if TYPE_CHECKING: + import datetime + class Auth(BaseModel): username: str @@ -18,7 +22,7 @@ class CreateUser(Auth): class UpdateUser(BaseModel): username: str email: str - mobile_number: Optional[str] = None + mobile_number: str | None = None class Avatar(BaseModel): @@ -28,9 +32,9 @@ class Avatar(BaseModel): class GetUserInfo(UpdateUser): id: int uid: str - avatar: Optional[str] = None + avatar: str | None = None time_joined: datetime.datetime = None - last_login: Optional[datetime.datetime] = None + last_login: datetime.datetime | None = None is_superuser: bool is_active: bool diff --git a/backend/app/utils/generate_string.py b/backend/app/utils/generate_string.py index 446e96f5..ec4965f8 100644 --- a/backend/app/utils/generate_string.py +++ b/backend/app/utils/generate_string.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import datetime import uuid diff --git a/backend/app/utils/re_verify.py b/backend/app/utils/re_verify.py index a5d27d8b..4979be3c 100644 --- a/backend/app/utils/re_verify.py +++ b/backend/app/utils/re_verify.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations import re diff --git a/docker_conf.py b/docker_conf.py index d5ae4d6e..218f08b8 100644 --- a/docker_conf.py +++ b/docker_conf.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from __future__ import annotations from functools import lru_cache from typing import Optional @@ -11,9 +12,9 @@ class Settings(BaseSettings): TITLE: str = 'FastAPI' VERSION: str = 'v0.0.1' DESCRIPTION: str = 'FastAPI Best Architecture' - DOCS_URL: Optional[str] = '/v1/docs' - REDOCS_URL: Optional[str] = None - OPENAPI_URL: Optional[str] = '/v1/openapi' + DOCS_URL: str | None = '/v1/docs' + REDOCS_URL: str | None = None + OPENAPI_URL: str | None = '/v1/openapi' # Static Server STATIC_FILES: bool = False diff --git a/gunicorn.conf.py b/gunicorn.conf.py index d4e789c6..23017d0c 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -1,4 +1,6 @@ # 监听内网端口 +from __future__ import annotations + bind = '0.0.0.0:8001' # 工作目录