Research-Stack/5-Applications/nodupe/pipeline/pyproject.toml
2026-05-05 21:15:26 -05:00

274 lines
8.7 KiB
TOML

# pyproject.toml
# ─────────────────────────────────────────────────────────────────────────────
# Unified tool configuration for NoDupeLabs.
# All thresholds match the Orchestrator prompt and .clinerules exactly.
# ─────────────────────────────────────────────────────────────────────────────
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.backends.legacy:build"
# ─── PROJECT METADATA ────────────────────────────────────────────────────────
[project]
name = "nodupe"
version = "1.0.0"
description = "Advanced duplicate file detection and management system"
readme = "README.md"
requires-python = ">=3.9"
[project.optional-dependencies]
dev = [
# Testing
"pytest>=8.0",
"pytest-cov>=5.0",
"pytest-xdist>=3.0",
"pytest-timeout>=2.3",
"coverage[toml]>=7.0",
"hypothesis>=6.0",
# Docstrings
"interrogate>=1.7",
# Type checking
"mypy>=1.9",
# Quality (fallback for when Project Health Auditor MCP is unavailable)
"radon>=6.0",
"pylint>=3.0",
"flake8>=7.0",
"flake8-bugbear>=24.0",
"flake8-docstrings>=1.7",
"flake8-simplify>=0.21",
"vulture>=2.11",
# Security (subprocess — pip-audit/safety always run; bandit is MCP fallback)
"bandit[toml]>=1.7",
"pip-audit>=2.7",
"safety>=3.0",
# Formatting
"black>=24.0",
"isort>=5.13",
]
# ─── PYTEST ──────────────────────────────────────────────────────────────────
[tool.pytest.ini_options]
minversion = "8.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--tb=short",
"--strict-markers",
"--strict-config",
"-ra",
"--cov=.",
"--cov-branch",
"--cov-report=term-missing",
"--cov-report=html:reports/coverage",
"--cov-report=xml:reports/coverage.xml",
"--cov-fail-under=80",
"--timeout=30",
]
markers = [
"unit: pure unit tests with no external dependencies",
"integration: tests that touch external systems",
"slow: tests that take longer than 5 seconds",
]
# ─── COVERAGE ────────────────────────────────────────────────────────────────
[tool.coverage.run]
branch = true
source = ["nodupe"]
omit = [
"tests/*",
"test_*.py",
"*_test.py",
"setup.py",
"conftest.py",
"scripts/*",
".venv/*",
"*/site-packages/*",
"__pycache__/*",
"*.pyi",
]
[tool.coverage.report]
fail_under = 80
show_missing = true
skip_covered = false
skip_empty = true
exclude_also = [
"def __repr__",
"def __str__",
"if TYPE_CHECKING:",
"@(abc\\.)?abstractmethod",
"raise NotImplementedError",
"\\.\\.\\.",
"if __name__ == .__main__.:",
]
precision = 2
[tool.coverage.html]
directory = "reports/coverage"
[tool.coverage.xml]
output = "reports/coverage.xml"
# ─── INTERROGATE ───────────────────────────────────────────────────────────
[tool.interrogate]
ignore-init-method = false
ignore-init-module = false
ignore-magic = false
ignore-semiprivate = false
ignore-private = true
ignore-property-decorators = false
ignore-module = false
ignore-nested-functions = false
ignore-nested-classes = false
ignore-setters = false
fail-under = 100
exclude = ["setup.py", "docs/", ".venv/", "build/", "dist/", "scripts/"]
verbose = 2
quiet = false
color = true
omit-covered-files = false
generate-badge = "reports/"
# ─── MYPY ───────────────────────────────────────────────────────────────────
[tool.mypy]
python_version = "3.9"
strict = true
warn_return_any = true
warn_unused_configs = true
warn_unused_ignores = true
warn_redundant_casts = true
warn_unreachable = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_calls = true
disallow_any_generics = true
disallow_any_unimported = true
no_implicit_optional = true
check_untyped_defs = true
show_error_codes = true
show_column_numbers = true
error_summary = true
pretty = true
exclude = ["build/", "dist/", ".venv/", "docs/", "scripts/"]
# ─── BLACK ─────────────────────────────────────────────────────────────────
[tool.black]
line-length = 100
target-version = ["py39"]
include = '\\.pyi?$'
extend-exclude = '''
/(
| \.venv
| build
| dist
| docs
| scripts
)/
'''
# ─── ISORT ─────────────────────────────────────────────────────────────────
[tool.isort]
profile = "black"
line_length = 100
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
split_on_trailing_comma = true
known_first_party = ["nodupe"]
sections = [
"FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER",
]
skip = [".venv", "build", "dist", "docs", "scripts"]
skip_glob = ["*.pyi"]
# ─── PYLINT (fallback — Project Health Auditor MCP is preferred) ─────────────
[tool.pylint.main]
fail-under = 9.0
jobs = 0
recursive = true
ignore = ["CVS", ".venv", "build", "dist", "docs", "scripts"]
ignore-patterns = ["test_.*\\.py", ".*_test\\.py", "conftest\\.py"]
[tool.pylint.messages_control]
disable = [
"C0114", # missing-module-docstring → interrogate handles this
"C0115", # missing-class-docstring → interrogate handles this
"C0116", # missing-function-docstring → interrogate handles this
"C0301", # line-too-long → black handles this
"C0303", # trailing-whitespace → black handles this
"C0304", # missing-final-newline → black handles this
"W0611", # unused-import → flake8 F401 handles this
]
[tool.pylint.design]
max-args = 10
max-attributes = 10
max-bool-expr = 5
max-branches = 20
max-locals = 25
max-parents = 7
max-public-methods = 20
max-returns = 6
max-statements = 75
[tool.pylint.format]
max-line-length = 120
[tool.pylint.similarities]
min-similarity-lines = 6
ignore-comments = true
ignore-docstrings = true
ignore-imports = true
# ─── BANDIT (fallback — Semgrep MCP is preferred) ───────────────────────────
[tool.bandit]
targets = ["."]
recursive = true
severity = "medium"
confidence = "medium"
exclude_dirs = [".venv", "build", "dist", "docs", "tests", "scripts"]
skips = []
# ─── VULTURE (fallback — Project Health Auditor MCP is preferred) ──────────
[tool.vulture]
min_confidence = 80
paths = ["nodupe"]
exclude = [".venv/", "build/", "dist/", "docs/", "scripts/"]
ignore_decorators = [
"@app.route",
"@pytest.fixture",
"@property",
"@staticmethod",
"@classmethod",
"@abstractmethod",
"@click.command",
"@click.option",
]
ignore_names = ["_", "setUp", "tearDown", "setUpClass", "tearDownClass",
"setUpModule", "tearDownModule"]
make_whitelist = false
# ─── RADON (fallback — Project Health Auditor MCP is preferred) ─────────────
# Radon does not support pyproject.toml — thresholds enforced via CLI in audit.py
# Target thresholds (match .clinerules and Orchestrator prompt):
# cyclomatic complexity : Grade C ceiling (CC ≤ 10)
# maintainability index : Grade B floor (MI ≥ 65)