[project]
name = "ondine"
version = "1.0.2"
description = "Ondine - The LLM Dataset Engine. Production-grade SDK for processing tabular datasets using LLMs with reliability, observability, and cost control"
requires-python = ">=3.10"
authors = [
    {name = "Binblok", email = "git@binblok.com"}
]
readme = "README.md"
license = {text = "MIT"}
keywords = ["llm", "dataset", "batch-processing", "data-engineering", "llama-index", "ai", "machine-learning", "data-transformation"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Topic :: Scientific/Engineering :: Artificial Intelligence",
]

dependencies = [
    "llama-index>=0.12.0",
    "llama-index-llms-openai>=0.3.0",
    "llama-index-llms-azure-openai>=0.3.0",
    "llama-index-llms-anthropic>=0.3.0",
    "llama-index-llms-groq>=0.3.0",
    "pandas>=2.0.0",
    "polars>=0.20.0",
    "pydantic>=2.0.0",
    "python-dotenv>=1.0.0",
    "tqdm>=4.66.0",
    "tenacity>=8.2.0",
    "openpyxl>=3.1.0",
    "pyarrow>=15.0.0",
    "tiktoken>=0.5.0",
    "structlog>=24.0.0",
    "jinja2>=3.1.0",
    "prometheus-client>=0.20.0",
    "click>=8.1.0",
    "rich>=13.0.0",
]

[project.urls]
Homepage = "https://github.com/ptimizeroracle/Ondine"
Repository = "https://github.com/ptimizeroracle/Ondine"
Documentation = "https://github.com/ptimizeroracle/Ondine#readme"
Issues = "https://github.com/ptimizeroracle/Ondine/issues"

[project.optional-dependencies]
dev = [
    "pytest>=8.0.0",
    "pytest-cov>=4.1.0",
    "pytest-asyncio>=0.23.0",
    "ruff>=0.8.0",
    "mypy>=1.13.0",
    "pre-commit>=4.0.0",
    "bandit>=1.7.0",
    "pip-audit>=2.7.0",
    "pip-licenses>=4.3.0",
    "ipython>=8.20.0",
    "jupyter>=1.0.0",
]
mlx = [
    "mlx>=0.29.0",
    "mlx-lm>=0.28.0",
]
observability = [
    "opentelemetry-api>=1.20.0",
    "opentelemetry-sdk>=1.20.0",
    "opentelemetry-exporter-jaeger>=1.20.0",
]

[project.scripts]
ondine = "ondine.cli.main:cli"
hermes = "ondine.cli.main:cli"  # Keep backward compatibility alias

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

[tool.hatch.build.targets.wheel]
packages = ["ondine"]

# Ruff configuration (replaces black, isort, flake8, etc.)
[tool.ruff]
line-length = 88  # Standard Python (PEP 8 recommends 79 but 88 is modern default)
target-version = "py310"
extend-exclude = [
    ".venv",
    "venv",
    "build",
    "dist",
    "*.egg-info",
]

[tool.ruff.lint]
select = [
    "E",      # pycodestyle errors
    "W",      # pycodestyle warnings
    "F",      # pyflakes
    "I",      # isort
    "N",      # pep8-naming
    "B",      # flake8-bugbear
    "C90",    # mccabe complexity
    "UP",     # pyupgrade
    "S",      # bandit security
    "T20",    # flake8-print
    "PT",     # flake8-pytest-style
    "RET",    # flake8-return
    "SIM",    # flake8-simplify
    "TCH",    # flake8-type-checking
]
ignore = [
    "E501",   # line too long (handled by formatter)
    "E402",   # module level import not at top (intentional for env setup)
    "S101",   # use of assert (fine in tests)
    "S108",   # hardcoded /tmp usage (fine for examples)
    "S301",   # pickle usage (needed for checkpoints)
    "S110",   # try-except-pass (intentional for observers)
    "S112",   # try-except-continue (intentional error handling)
    "T201",   # print statements (needed for CLI/examples)
    "B007",   # unused loop variable (common in pandas iterrows)
    "B017",   # pytest.raises(Exception) (acceptable in tests)
    "B027",   # empty abstract method without decorator (optional hooks)
    "B904",   # raise within except without from (acceptable)
    "C901",   # too complex (acceptable for main execute functions)
    "PT011",  # pytest.raises too broad (acceptable)
    "SIM105", # contextlib.suppress suggestion (readability preference)
    "SIM108", # ternary operator suggestion (readability preference)
    "SIM102", # nested if simplification (readability preference)
    "S603",   # subprocess without shell=True
    "S607",   # starting process with partial path
]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "PLR2004", "PLR0913"]
"examples/**/*.py" = ["T201", "S105"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false  # Gradually enable
check_untyped_defs = true
ignore_missing_imports = true

[tool.bandit]
exclude_dirs = ["tests", ".venv", "venv"]
skips = ["B101"]  # assert_used - fine in tests

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --cov=ondine --cov-report=term-missing"
markers = [
    "integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
]
filterwarnings = [
    "ignore::pydantic.warnings.PydanticDeprecatedSince20",
    "ignore::pydantic._internal._generate_schema.UnsupportedFieldAttributeWarning",
]
