# ============================================================================
# BUILD SYSTEM & PROJECT METADATA
# ============================================================================
# Core project configuration - rarely modified after initial setup
[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools>=80.9.0,<81.0.0", "wheel>=0.45.1,<1.0.0"]
[project]
authors = [
{name = "AI Debugger", email = "info@ai-debugger.com"}
]
description = """A lightweight Python API that enables AI systems to
programmatically control and introspect live debugging sessions."""
dependencies = [
"aiofiles>=23.0.0,<26.0.0",
"mcp>=1.0.0,<2.0.0",
"psutil>=5.9.0,<8.0.0",
]
keywords = ["AI Debugger", "aidb", "debugging"]
license = {file = "LICENSE"}
name = "ai-debugger-inc"
classifiers = [
"License :: OSI Approved :: Apache Software License",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Debuggers",
"Operating System :: MacOS",
"Operating System :: POSIX :: Linux",
]
readme = "README.md"
requires-python = ">=3.10"
version = "0.1.1"
[project.urls]
Homepage = "https://github.com/ai-debugger-inc/aidb"
Documentation = "https://ai-debugger.com"
"Issue Tracker" = "https://github.com/ai-debugger-inc/aidb/issues"
[project.scripts]
aidb-mcp = "aidb_mcp.cli:main"
[project.optional-dependencies]
# Development tools for dev-cli, linting, testing, and CI/CD
dev = [
# dev-cli dependencies (not user-facing)
"click>=8.0.0,<9.0.0",
"jinja2>=3.1.0,<4.0.0",
# CI/CD scripts (.github/)
"requests>=2.32.2,<3.0.0",
# Performance testing (optional tiktoken for accurate token estimation)
"tiktoken>=0.8.0,<1.0.0",
# Code quality & formatting
"docformatter>=1.7.0,<2.0.0",
"mdformat>=0.7.0,<2.0.0",
"mypy>=1.18.2,<2.0.0",
"pydocstyle>=6.3.0,<7.0.0",
"ruff>=0.14.4,<1.0.0",
# Security & dependency analysis
"bandit>=1.8.6,<2.0.0",
"deptry>=0.24.0,<1.0.0",
"safety>=3.7.0,<4.0.0",
"vulture>=2.14,<3.0",
# Development utilities
"anthropic>=0.45.0,<1.0.0",
"pre-commit>=4.4.0,<5.0.0",
"python-dotenv>=1.2.1,<2.0.0",
"pyyaml>=6.0,<8.0",
"tomli>=2.3.0,<3.0.0",
"yamllint>=1.37.1,<2.0.0",
# Type stubs
"types-aiofiles>=25.1.0,<26.0.0",
"types-docutils>=0.21.0,<1.0.0",
"types-PyYAML>=6.0.0,<7.0.0",
"types-requests>=2.32.0,<3.0.0",
"types-setuptools>=80.9.0,<81.0.0",
# Build tools
"build>=1.3.0,<2.0.0",
"setuptools>=80.9.0,<81.0.0",
"wheel>=0.45.1,<1.0.0",
]
# CI validation
ci-validation = [
"aiofiles>=24.1.0,<26.0.0",
"click>=8.0.0,<9.0.0",
"jinja2>=3.1.6,<4.0.0",
"psutil>=7.0.0,<8.0.0",
"pyyaml>=6.0,<8.0",
]
# Public documentation dependencies (readthedocs.io)
docs = [
"linkify-it-py>=2.0.3,<3.0.0",
"myst_parser>=4.0.1,<5.0.0",
"pydata-sphinx-theme>=0.16.1,<1.0.0",
"sphinx>=8.2.3,<9.0.0",
"sphinx-autoapi>=3.0.0,<4.0.0",
"sphinx-click>=6.0.0,<7.0.0",
"sphinx-copybutton>=0.5.2,<1.0.0",
"sphinx-design>=0.6.1,<1.0.0",
"sphinx-favicon>=1.0.1,<2.0.0",
"sphinxcontrib-mermaid>=1.0.0,<2.0.0",
"tomli>=2.3.0,<3.0.0; python_version < '3.11'",
]
# Testing dependencies
test = [
"coverage>=7.11.2,<8.0.0",
"docker>=7.1.0,<8.0.0",
"python-dotenv>=1.2.1,<2.0.0",
"pytest>=8.2.0,<10.0.0",
"pytest-asyncio>=1.2.0,<2.0.0",
"pytest-cov>=7.0.0,<8.0.0",
"pytest-mock>=3.15.1,<4.0.0",
"pytest-rerunfailures>=16.1,<17.0",
"pytest-timeout>=2.4.0,<3.0.0",
"pytest-xdist>=3.8.0,<4.0.0",
"responses>=0.25.8,<1.0.0",
]
# ============================================================================
# CODE FORMATTING & STYLE
# ============================================================================
# Automated code formatting and import organization
[tool.docformatter]
wrap-summaries = 88
wrap-descriptions = 88
[tool.ruff]
line-length = 88
target-version = "py310"
src = ["src"]
exclude = ["*.md"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C90", # mccabe complexity
"N", # pep8-naming
"UP", # pyupgrade
"S", # flake8-bandit
"A", # flake8-builtins
"ASYNC", # flake8-async - detect missing await
"COM", # flake8-commas
"DTZ", # flake8-datetimez
"EM", # flake8-errmsg
"G", # flake8-logging-format
"ICN", # flake8-import-conventions
"PIE", # flake8-pie
"PT", # flake8-pytest-style
"Q", # flake8-quotes
"RET", # flake8-return
"SIM", # flake8-simplify
"TCH", # flake8-type-checking
"ARG", # flake8-unused-arguments
"PTH", # flake8-use-pathlib
]
ignore = [
"N815", # variable in function should be lowercase - DAP/JSON camelCase
]
[tool.ruff.lint.mccabe]
max-complexity = 15
[tool.ruff.lint.per-file-ignores]
"src/tests/**/*.py" = [
"E501", # line too long - tests often have long fixture names and data
"F401", "S101", "S105", "S106", "S108", "S602", "S603", "S607", # unused imports, asserts, test secrets, subprocess in tests
"F811", # redefinition - common with pytest fixtures
"A001", "A002", "A003", # builtin shadowing - common in tests (e.g., `license` variable)
"ARG001", "ARG002", "ARG005", # unused arguments - common with pytest fixtures and mocks
"SIM117", # nested with statements - often more readable in tests
"G004", # f-string logging - negligible perf impact in test code, readability preferred
"PTH123", # open() vs Path.open() - acceptable in tests for simplicity
"COM812", # trailing comma - handled by formatter
"PT011", "PT012", # pytest.raises patterns - acceptable in tests
"TC003", # type-checking imports - unnecessary complexity in tests
]
"scripts/**/*.py" = ["E501", "S607", "S603"] # line too long, safe subprocess calls with docker/git
".github/**/*.py" = ["E501"] # line too long - CI scripts often have long URLs and commands
"src/aidb/dap/_util/**/*.py" = ["ALL"] # ignore all rules in generated utility code
"src/aidb/dap/protocol/**/*.py" = ["ALL"] # ignore all rules in DAP protocol spec (generated/spec-defined)
"src/tests/_assets/test_programs/generated/**/*.py" = ["ALL"] # ignore all rules in generated test programs
"src/aidb/adapters/base/subprocess_validator.py" = ["S603"] # safe subprocess calls with hardcoded commands
"src/aidb_mcp/starters/*.py" = ["S603", "S104"] # safe subprocess calls, dev server configs
"docs/conf.py" = ["A001"] # copyright is required by Sphinx
"**/__init__.py" = ["F401"] # unused imports in __init__.py are re-exports
# DAP client - internal implementation with intentional patterns
"src/aidb/dap/client/*.py" = ["S110", "E501", "N806"] # try-except-pass for resilience, long lines in comments, ContinueRequest naming
# Java adapter - diagnostic code uses best-effort error suppression
"src/aidb/adapters/lang/java/lsp/jdtls_process_manager.py" = ["S110", "S108"] # diagnostic best-effort, /dev/shm check
"src/aidb/adapters/lang/java/lsp/lsp_bridge.py" = ["E501"] # long warning messages
# Session ops - debug logging with long messages
"src/aidb/session/ops/introspection_mixin.py" = ["E501", "S110"] # debug logging, exception handling
"src/aidb/session/ops/initialization.py" = ["SIM105"] # contextlib.suppress not appropriate for async
"src/aidb/session/ops/orchestration/stepping.py" = ["ARG002"] # wait_for_stop kept for API compatibility
# CLI - pre-existing patterns
"src/aidb_cli/managers/base/service.py" = ["G003"] # logging pattern with class prefix
"src/aidb_cli/managers/build/build_manager.py" = ["SIM105", "S110", "ARG002"] # lazy init, unused force param
"src/aidb_cli/services/docker/docker_resource_service.py" = ["E501"] # long docstring line
"src/aidb_cli/services/test/test_execution_service.py" = ["S607"] # bash subprocess intentional
# Common - pre-existing
"src/aidb_common/config/versions.py" = ["S101"] # assert for invariant
"src/aidb_common/patterns/singleton.py" = ["E501"] # long error message
# ============================================================================
# CODE QUALITY & ANALYSIS
# ============================================================================
# Type checking, documentation, security, and dependency analysis
[tool.mypy]
check_untyped_defs = true
explicit_package_bases = true
ignore_missing_imports = true
python_version = "3.10"
[tool.pydocstyle]
convention = "numpy"
add-ignore = ["D105", "D301"]
[tool.bandit]
exclude_dirs = ["src/tests", "src/aidb/dap/_util", "src/aidb/dap/protocol"]
skips = ["B101", "B104", "B108", "B603"]
[tool.deptry]
exclude = [
"scripts",
"docs",
".github",
"src/tests",
"src/aidb/dap/_util",
"src/aidb/dap/protocol",
]
pep621_dev_dependency_groups = ["dev", "test", "docs"]
extend_exclude = [
".venv",
"venv",
"armored",
"build",
".cache",
]
ignore = ["DEP003"]
known_first_party = ["aidb", "aidb_common", "aidb_logging", "aidb_cli", "aidb_mcp"]
ignore_notebooks = true
[tool.deptry.package_module_name_map]
sphinx-autoapi = "autoapi"
sphinx-click = "sphinx_click"
sphinxcontrib-mermaid = "sphinxcontrib.mermaid"
[tool.deptry.per_rule_ignores]
DEP004 = [
"click", "tomli", "jinja2", "sphinx-click", "sphinx_click", "yaml", "tiktoken"
]
DEP001 = ["src", "sphinx_click"]
# ============================================================================
# TESTING & COVERAGE
# ============================================================================
# Test execution, markers, and coverage reporting
# NOTE: This section is frequently modified when adding new test markers
[tool.pytest.ini_options]
minversion = "6.0"
addopts = [
"-ra",
"--strict-markers",
"--strict-config",
"--tb=short"
]
testpaths = ["src/tests"]
norecursedirs = [
"test_programs",
"node_modules",
"framework_apps",
"_assets",
]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
asyncio_mode = "auto"
# Use session-scoped event loops to enable JDT LS pooling across tests
# Without this, each test gets a new loop, defeating the pooling mechanism
asyncio_default_fixture_loop_scope = "session"
markers = [
# Core test types
"asyncio: Mark test as async (from pytest-asyncio)",
"unit: Isolated unit tests",
"integration: Component boundary tests",
"e2e: End-to-end workflows",
"smoke: Quick validation tests (<60s total)",
# Language markers (auto-applied by location)
"language_python: Mark test to run in Python container",
"language_javascript: Mark test to run in JavaScript container",
"language_java: Mark test to run in Java container",
# Infrastructure requirements
"requires_docker: Needs Docker environment",
# Execution characteristics
"serial: Tests that must run serially (no parallelization)",
"slow: Takes >5 seconds",
"performance: Performance tests (timing-sensitive)",
# pytest-xdist
"xdist_group(name): Group tests to run on the same worker (pytest-xdist)",
]
filterwarnings = [
"error",
"ignore::UserWarning",
"ignore::DeprecationWarning",
"ignore::PendingDeprecationWarning"
]
timeout = 300
# Automatic retry for flaky tests (1 retry globally)
reruns = 1
reruns_delay = 0
# Logging configuration for pytest
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] [%(name)s] %(message)s"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
# File logging for persistent test logs
# Local: Written to {repo_root}/pytest-logs/pytest-captured.log
# Container: Written to /workspace/pytest-logs/ (mounted to .cache/container-data/aidb-test-{lang}/pytest/)
log_file = "pytest-logs/pytest-captured.log"
log_file_level = "DEBUG"
log_file_format = "%(asctime)s [%(levelname)8s] [%(name)s] %(message)s"
log_file_date_format = "%Y-%m-%d %H:%M:%S"
log_level = "DEBUG"
[tool.coverage.run]
source = ["src/aidb", "src/aidb_mcp", "src/aidb_cli", "src/aidb_common", "src/aidb_logging"]
omit = [
"*/tests/*",
"*/test_*",
"*/__init__.py",
"*/conftest.py"
]
branch = true
parallel = true
[tool.coverage.paths]
# Map container paths to local paths for coverage combine
# First path in each list is the canonical path used in reports
source = [
"src/",
"/workspace/src/",
"/home/runner/work/aidb/aidb/src/",
]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod"
]
# ============================================================================
# BUILD & PACKAGING
# ============================================================================
# Package discovery and resource bundling configuration
[tool.setuptools.package-dir]
"" = "src"
[tool.setuptools.packages.find]
where = ["src"]
exclude = [
"tests*",
"tests.*",
"aidb_cli",
"aidb_cli.*",
]
[tool.setuptools.package-data]
aidb = [
"resources/*.vsix",
"resources/**/*"
]