[project]
name = "ai"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = "~=3.13"
dependencies = [
    "granian==2.5",
    "jinja2>=3.1.6",
    "numpy==2.3.4",
    "pillow>=11.1.0",
    "markdown>=3.9",
    "aiocache",
    "torch>=2.9.1",
    "ruff>=0.14.5",
    "mypy>=1.18.2",
    "uvicorn>=0.38.0",
    "pydantic>=2.12.4",
    "litestar==2.18.0",
    "ujson>=5.11.0",
    "torchvision>=0.24.1",
    "types-requests>=2.32.4.20250913",
    "types-markdown>=3.10.0.20251106",
    "sqlalchemy>=2.0.44",
    "inject>=5.3.0",
    "aiofiles>=25.1.0",
    "botocore>=1.42.9",
    "types-aiofiles>=25.1.0.20251011",
    "betterconf>=4.5.0",
    "dataclasses-ujson>=0.0.34",
    "asyncpg>=0.31.0",
    "alembic>=1.18.0",
    "aioboto3>=7.0.0",
    "boto3>=1.42.9",
    "python-magic>=0.4.27",
    "psycopg2-binary>=2.9.11",
]

[project.optional-dependencies]
default = [
    "torch>=2.9.1",
    "torchvision>=0.21.0",
    "mypy>=1.18",
    "pyqt5>=5.15.11",
    "requests>=2.32.3",
    "ruff>=0.11.5",
    "types-requests>=2.32.0.20250328",
    "matplotlib>=3.10.1",
]


# MYPY

[tool.mypy]
exclude = [
    ".venv",
    "venv",
    "tmp",
    "scripts",
    "tests"
]
plugins = ["sqlalchemy.ext.mypy.plugin"]
mypy_path = "./stubs"
ignore_missing_imports = true

# RUFF

[tool.ruff]
target-version = "py312"
show-fixes = true
src = ["app"]
# Same as Black.
line-length = 120
indent-width = 4

# Exclude a variety of commonly ignored directories.
exclude = [
    ".bzr",
    ".direnv",
    ".eggs",
    ".git",
    ".git-rewrite",
    ".hg",
    ".ipynb_checkpoints",
    ".mypy_cache",
    ".nox",
    ".pants.d",
    ".pyenv",
    ".pytest_cache",
    ".pytype",
    ".ruff_cache",
    ".svn",
    ".tox",
    ".venv",
    ".vscode",
    "__pypackages__",
    "_build",
    "buck-out",
    "build",
    "dist",
    "node_modules",
    "site-packages",
    "venv",
    "stubs",
    "scripts",
]

[tool.ruff.lint.isort]
known-first-party = ["app"]

[tool.ruff.format]
# Like Black, use double quotes for strings.
quote-style = "double"
# Like Black, indent with spaces, rather than tabs.
indent-style = "space"
# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false
# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

[tool.ruff.lint.per-file-ignores]
"stubs/*" = ["F403"]
"server/migration/*" = ["E501", "F403"]
"server/config/__init__.py" = ["E501"]
"scripts/*" = ["T201", "E501"]
"server/admin/*" = ["E501", "E711"]
"vk_api/*"= ["T201", "C416", "A001", "E501"]
"ml/*"= ["T201", "C416", "A001", "E501", "C416", "N812"]
"tests/**/*.py" = [
    "E501", "ASYNC230",
    # at least this three should be fine in tests:
    "S101", # asserts allowed in tests...
    "S106", # Possible hardcoded password assigned to argument: "password"
    "S110", # consider logging the exception
    "ARG", # Unused function args -> fixtures nevertheless are functionally relevant...
    "FBT", # Don't care about booleans as positional arguments in tests, e.g. via @pytest.mark.parametrize()
    # The below are debateable
    "PLR2004", # Magic value used in comparison, ...
    "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes
    "INP001", # File `...` is part of an implicit namespace package. Add an `__init__.py`.
    "SLF001", # Private member accessed: `_...`
]
"tests/__init__.py" = ["I001"]

[tool.ruff.lint]
# https://docs.astral.sh/ruff/rules/
select = ["DTZ", "F", "C4", "B", "A", "E", "T", "I", "N", "UP", "ASYNC", "Q"]
ignore = ["E712", "B904", "B019", "C417"]

# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[tool.ruff.lint.mccabe]
# https://docs.astral.sh/ruff/settings/#mccabe
# Flag errors (`C901`) whenever the complexity level exceeds 5.
max-complexity = 12

[tool.ruff.lint.flake8-pytest-style]
# https://docs.astral.sh/ruff/settings/#flake8-pytest-style
fixture-parentheses = false
mark-parentheses = false
