[project] name = "brewman" version = "15.1.4" description = "Accounting plus inventory management for a restaurant." requires-python = ">=3.14" authors = [{ name = "tanshu", email = "git@tanshu.com" }] dependencies = [ "alembic>=1.19.1", "arq>=0.28.0", "cryptography>=50.0.0", "fastapi[all]>=0.141.1", "gunicorn>=26.2.0", "itsdangerous>=2.2.0", "openpyxl>=3.1.5", "pandas>=3.0.5", "passlib[bcrypt]>=1.7.4", "psycopg[binary,pool]>=3.3.4", "pydantic>=2.13.4", "pydantic-settings>=2.15.0", "pyjwt>=2.13.0", "python-dotenv>=1.2.3", "python-multipart>=0.0.32", "sqlalchemy>=2.0.52", "uvicorn[standard]>=0.52.4", ] [dependency-groups] dev = [ "bandit>=1.9.4", "mypy>=2.3.1", "pandas-stubs>=3.0.5.260730", "pre-commit>=4.6.2", "ruff>=0.16.4", "safety>=3.8.1", "types-openpyxl>=3.1.5.20260807", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.mypy] # --- Strictness --- strict = true # Good safety defaults warn_return_any = true warn_unused_configs = true warn_redundant_casts = true warn_unused_ignores = true no_implicit_optional = true strict_equality = true warn_unreachable = true # Practical ergonomics pretty = true show_column_numbers = true error_summary = true # These keep signal high in real-world FastAPI projects disallow_any_generics = true check_untyped_defs = true # Start here; tighten later disallow_untyped_calls = true disallow_incomplete_defs = true disallow_subclassing_any = true disallow_untyped_defs = true disallow_untyped_decorators = true # enterprise backend strict # disallow_any_expr = true # disallow_any_decorated = true disallow_any_unimported = true plugins = ["sqlalchemy.ext.mypy.plugin", "pydantic.mypy"] [tool.pydantic-mypy] init_forbid_extra = true init_typed = true warn_required_dynamic_aliases = true [tool.ruff] line-length = 120 # Assume Python 3.14. target-version = "py314" exclude = [ ".eggs", ".git", ".hg", ".mypy_cache", ".tox", ".venv", "_build", "buck-out", "build", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "ARG001", # unused arguments in functions "T201", # print statements are not allowed ] ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults "W191", # indentation contains tabs "B904", # Allow raising exceptions without from e, for HTTPException ] fixable = ["ALL"] # Allow fix for all enabled rules (when `--fix`) is provided. dummy-variable-rgx = "^(user|_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.lint.isort] # include-trailing-comma = true lines-after-imports = 2 lines-between-types = 1 # use-parentheses = true [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto"