[project]
name = "cerbero-bite"
version = "0.0.1"
description = "Rule-based deterministic engine for Cerberus Bite credit spread strategy on ETH options"
readme = "README.md"
requires-python = ">=3.12"
authors = [{ name = "Adriano Dal Pastro", email = "adrianodalpastro@tielogic.com" }]
license = { text = "Proprietary" }

dependencies = [
    "pydantic>=2.9",
    "pydantic-settings>=2.5",
    "click>=8.1",
    "rich>=13.9",
    "structlog>=24.4",
    "apscheduler>=3.10",
    "sqlalchemy>=2.0",
    "aiosqlite>=0.20",
    "pyyaml>=6.0",
    "httpx>=0.27",
    "tenacity>=9.0",
    "python-dateutil>=2.9",
    "python-dotenv>=1.2.2",
]

[project.optional-dependencies]
gui = [
    "streamlit>=1.40",
    "plotly>=5.24",
    "pandas>=2.2",
    "numpy>=2.0",
]
backtest = [
    "scipy>=1.14",
    "matplotlib>=3.9",
    "pandas>=2.2",
    "numpy>=2.0",
]

[project.scripts]
cerbero-bite = "cerbero_bite.cli:main"

[dependency-groups]
dev = [
    "pytest>=8.3",
    "pytest-asyncio>=0.24",
    "pytest-cov>=5.0",
    "pytest-httpx>=0.33",
    "hypothesis>=6.115",
    "mypy>=1.13",
    "ruff>=0.7",
    "pre-commit>=4.0",
    "types-PyYAML>=6.0",
    "types-python-dateutil>=2.9",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/cerbero_bite"]

[tool.ruff]
line-length = 100
target-version = "py312"
src = ["src", "tests"]

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "UP",   # pyupgrade
    "N",    # pep8-naming
    "SIM",  # flake8-simplify
    "RET",  # flake8-return
    "ARG",  # flake8-unused-arguments
    "PTH",  # flake8-use-pathlib
    "ERA",  # eradicate
    "PL",   # pylint
    "RUF",  # ruff-specific
]
ignore = [
    "PLR0913",  # too many arguments (we accept config-heavy functions)
    "PLR2004",  # magic value (we have many domain constants in tests)
    "PLR0911",  # too many return statements (rule engines have many early returns)
    "PLR0912",  # too many branches (entry/monitor cycles are inherently long)
    "PLR0915",  # too many statements (orchestration cycles)
    "RUF001",  # ambiguous unicode in strings (we use math symbols × ≤ ≥)
    "RUF002",  # ambiguous unicode in docstrings
    "RUF003",  # ambiguous unicode in comments
]

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["PLR2004", "ARG", "S101", "ERA001", "B017"]
# Streamlit auto-discovers pages whose file names start with a number and
# may contain icons; the convention conflicts with N999.
"src/cerbero_bite/gui/pages/*" = ["N999"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

[tool.mypy]
python_version = "3.12"
strict = true
warn_unreachable = true
warn_redundant_casts = true
warn_unused_ignores = true
disallow_any_generics = true
disallow_untyped_defs = true
no_implicit_reexport = true
files = ["src/cerbero_bite"]

[[tool.mypy.overrides]]
module = ["apscheduler.*", "plotly.*", "pandas.*"]
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
addopts = [
    "-ra",
    "--strict-markers",
    "--strict-config",
]
markers = [
    "slow: marks tests as slow (deselect with '-m \"not slow\"')",
    "integration: integration tests with fake MCP",
    "golden: golden scenario tests",
]

[tool.coverage.run]
source = ["src/cerbero_bite"]
branch = true

[tool.coverage.report]
exclude_lines = [
    "pragma: no cover",
    "raise NotImplementedError",
    "if TYPE_CHECKING:",
    "if __name__ == .__main__.:",
]
show_missing = true
skip_covered = false
