[project]
name = "spatial-audio-validation"
version = "0.1.0"
description = "Spatial audio validation for Apple Music delivery"
requires-python = ">=3.14,<3.15"
dependencies = [
    "pydantic~=2.12",
    "pydantic-settings~=2.13",
    "boto3~=1.42",
    "sentry-sdk~=2.57",
    "ddtrace~=4.6",
    "owsclient~=0.9",
    "secrets-manager~=1.4",
    # Seekable S3 file-like for the EAR renderer (boto3-backed; no aiobotocore,
    # so no conflict with the boto3 pin above). See src/clients/s3.py.
    "smart-open~=7.6",
    # Runtime dependencies of the vendored EAR package (src/vendor/README.md).
    # Upstream pins numpy~=1.14 (no cp314 wheels); numpy>=2,<3 is the override
    # we own, validated by EAR's full test suite on Python 3.14 + NumPy 2.
    "numpy>=2,<3",
    "scipy~=1.17",
    "lxml~=6.1",
    "attrs~=26.1",
    "pyyaml~=6.0",
    "six~=1.17",
    "multipledispatch~=1.0",
    "importlib-resources~=6.5",
]

[dependency-groups]
dev = [
    "ruff~=0.15",
    "mypy~=1.20",
    "pytest~=9.0",
    "pytest-cov~=7.1",
    "yamllint~=1.38",
    "boto3-stubs[s3,sqs,stepfunctions]~=1.42",
    "botocore-stubs~=1.42",
]

[tool.uv]
package = false
python-preference = "only-system"

[[tool.uv.index]]
name = "theorchard"
url = "https://pypi.theorchard.io/simple/"

[tool.uv.sources]
owsclient = { index = "theorchard" }
secrets-manager = { index = "theorchard" }

[tool.ruff]
target-version = "py314"
line-length = 120
src = ["src", "tests", "dev"]
extend-exclude = ["src/vendor"]

[tool.ruff.lint]
select = ["C4", "E", "F", "W", "B", "I", "T20", "TID252", "G", "UP", "SIM", "RUF", "PT", "DTZ", "PERF", "LOG", "RET"]
ignore = ["E501"]

[tool.ruff.lint.isort]
combine-as-imports = true
forced-separate = ["tests"]

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101", "TC003"]
"dev/**" = ["T20"]

[tool.mypy]
python_version = "3.14"
strict = true
explicit_package_bases = true
exclude = ["(^|/)\\.venv/", "^build/", "^src/vendor/"]
plugins = ["pydantic.mypy"]

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
warn_required_dynamic_aliases = true

[[tool.mypy.overrides]]
module = "secrets_manager.*"
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = ["smart_open", "smart_open.*"]
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "scipy.*"
ignore_missing_imports = true

# Vendored, untyped, and off mypy's search path (resolved at runtime via the
# src/__init__.py sys.path shim — see src/vendor/README.md).
[[tool.mypy.overrides]]
module = "ear.*"
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = ["-ra", "--strict-markers", "--strict-config"]

[tool.coverage.run]
omit = ["src/vendor/*"]
