[project] name = "fastapi_best_architecture" description = "FastAPI 企业级后端架构解决方案" readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } authors = [ { name = "Wu Clan", email = "jianhengwu0407@gmail.com" }, ] dependencies = [ "alembic>=1.18.3", "asgiref>=3.11.0", "asyncmy>=0.2.11", "asyncpg>=0.31.0", "bcrypt>=5.0.0", # If there is a serious problem, we will try `moka-py` "cachebox>=5.2.2", "cappa>=0.31.0", "celery>=5.6.2", # When celery version < 6.0.0 # https://github.com/celery/celery/issues/7874 "celery-aio-pool>=0.1.0rc8", "cryptography>=46.0.4", "dulwich>=1.0.0", "fast-captcha>=0.3.2", "fastapi-limiter>=0.1.6", "fastapi-pagination>=0.15.9", "fastapi[standard-no-fastapi-cloud-cli]>=0.128.0", "flower>=2.0.1", "gevent>=25.9.1", "granian>=2.7.0", "ip2loc>=1.0.0", "itsdangerous>=2.2.0", "jinja2>=3.1.6", "loguru>=0.7.3", "msgspec>=0.20.0", "opentelemetry-exporter-otlp-proto-grpc>=1.39.1", "opentelemetry-instrumentation-asyncio>=0.60b1", "opentelemetry-instrumentation-celery>=0.60b1", "opentelemetry-instrumentation-fastapi>=0.60b1", "opentelemetry-instrumentation-httpx>=0.60b1", "opentelemetry-instrumentation-logging>=0.60b1", "opentelemetry-instrumentation-redis>=0.60b1", "opentelemetry-instrumentation-sqlalchemy>=0.60b1", "opentelemetry-sdk>=1.39.1", "prometheus-client>=0.24.1", "psutil>=7.2.2", # https://github.com/fastapi-practices/fastapi_best_architecture/issues/887 "psycopg[binary]==3.2.10", "pwdlib>=0.3.0", "pydantic>=2.12.5", "pydantic-settings>=2.12.0", "pymysql>=1.1.2", "python-jose>=3.5.0", "python-socketio>=5.16.0", "redis[hiredis]>=7.1.0", "rtoml>=0.13.0", "sqlalchemy-crud-plus>=1.13.1", "sqlalchemy[asyncio]>=2.0.46", "sqlparse>=0.5.5", "starlette-context>=0.4.0", "user-agents>=2.2.0", ] dynamic = ["version"] [project.scripts] fba = "backend.cli:main" [dependency-groups] dev = [ "pytest>=9.0.2", "pytest-sugar>=1.1.1", ] lint = [ "prek>=0.3.1", ] server = [ "aio-pika>=9.5.8", "wait-for-it>=2.3.0", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.alembic] script_location = "%(here)s/backend/alembic" file_template = "%%(year)d-%%(month).2d-%%(day).2d-%%(hour).2d_%%(minute).2d_%%(second).2d-%%(rev)s_%%(slug)s" prepend_sys_path = ["."] version_locations = ["%(here)s/backend/alembic/versions"] [tool.hatch.build.targets.wheel] packages = ["backend"] [tool.hatch.version] path = "backend/__init__.py" [tool.ruff] line-length = 120 preview = true fix = true unsafe-fixes = true show-fixes = true required-version = ">=0.15.0" [tool.ruff.lint] select = [ "FAST", "ANN001", "ANN201", "ANN202", "ANN204", "ANN205", "ANN206", "ASYNC110", "ASYNC116", "ASYNC210", "ASYNC212", "ASYNC230", "ASYNC240", "ASYNC250", "ASYNC251", "S310", "FBT001", "FBT002", "B002", "B005", "B006", "B007", "B008", "B009", "B010", "B013", "B014", "B019", "B020", "B021", "B024", "B025", "B026", "B027", "B039", "COM", "C402", "C403", "C404", "C408", "C410", "C411", "C414", "C416", "C417", "C418", "C419", "C420", "DTZ", "EXE", "ISC001", "ISC002", "ISC003", "PIE", "PYI009", "PYI010", "PYI011", "PYI012", "PYI013", "PYI016", "PYI017", "PYI019", "PYI020", "PYI021", "PYI024", "PYI026", "PYI030", "PYI033", "PYI034", "PYI036", "PYI041", "PYI042", "PYI055", "PYI061", "PYI062", "PYI063", "Q001", "Q002", "RSE102", "RET501", "RET505", "RET506", "RET507", "RET508", "SIM101", "SIM102", "SIM103", "SIM107", "SIM108", "SIM109", "SIM110", "SIM114", "SIM115", "SIM201", "SIM202", "SIM210", "SIM211", "SIM212", "SIM300", "SIM401", "SIM910", "TID252", "TC", "FLY", "I", "C901", "N", "PERF", "E", "W", "D404", "D417", "D419", "F", "PGH", "PLC1901", "UP", "FURB", "RUF", "TRY", ] ignore = [ "COM812", "PGH003", "RUF001", "RUF002", "RUF003", "RUF006", "RUF012", "RUF067", "TRY400", "TRY003", "TRY301" ] [tool.ruff.lint.per-file-ignores] "**/model/*.py" = ["TC003"] "backend/common/socketio/server.py" = ["ANN001"] "backend/common/exception/exception_handler.py" = ["ANN202", "RUF029"] [tool.ruff.lint.flake8-pytest-style] parametrize-names-type = "list" parametrize-values-row-type = "list" parametrize-values-type = "list" [tool.ruff.lint.flake8-quotes] inline-quotes = "single" [tool.ruff.lint.flake8-type-checking] runtime-evaluated-base-classes = [ "pydantic.BaseModel", "sqlalchemy.orm.DeclarativeBase" ] [tool.ruff.lint.flake8-unused-arguments] ignore-variadic-names = true [tool.ruff.lint.isort] case-sensitive = true lines-between-types = 1 order-by-type = true [tool.ruff.lint.pylint] allow-dunder-method-names = ["__tablename__", "__table_args__"] [tool.ruff.format] docstring-code-format = true preview = true quote-style = "single" [tool.tombi] toml-version = "v1.1.0" [[tool.tombi.schemas]] path = ".schemas/plugin.schema.json" include = ["backend/plugin/**/plugin.toml"] [tool.uv] python-downloads = "manual" default-groups = ["dev", "lint"] [[tool.uv.index]] name = "aliyun" url = "https://mirrors.aliyun.com/pypi/simple"