content: [project]
  name = "common"
  version = "0.1.0"
  description = "Shared utilities and components for Buttercup CRS"
  authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
  license = "AGPL-3.0-only"
  requires-python = ">=3.12,<3.13"
  dependencies = [
      "pydantic-settings ~=2.7.1",
      "pymongo ~=4.10.1",
      "redis ~=5.2.1",
      "langchain-core ~=0.3.74",
      "langchain-openai ~=0.3.30",
      "langchain ~=0.3.27",
      "langfuse ~=2.59.2",
      "six ~=1.17.0",
  ]
  
  [project.optional-dependencies]
  full = [
      "protobuf>=5.0",
      "openlit ==1.35.0",
  ]
  
  
  [project.urls]
  Repository = "https://github.com/trailofbits/buttercup"
  Issues = "https://github.com/trailofbits/buttercup/issues"
  
  [project.scripts]
  buttercup-util = "buttercup.common.util_cli:main"
  buttercup-challenge-task = "buttercup.common.challenge_task_cli:main"
  buttercup-task-registry = "buttercup.common.task_registry:task_registry_cli"
  
  
  [tool.hatch.build.targets.wheel]
  packages = ["src/buttercup"]
  
  [build-system]
  requires = ["hatchling"]
  build-backend = "hatchling.build"
  
  [dependency-groups]
  dev = [
      # Testing tools
      "pytest ~=8.3.4",
      "pytest-cov ~=6.0.0",
      "dirty-equals ~=0.9.0",
      # Linting and type checking
      "ruff ~=0.12.8",
      "mypy ~=1.17.1",
      # Type stubs
      "types-requests ~=2.32.0",
      "types-PyYAML",
      "types-redis ~=4.6.0",
  ]
  
  [tool.ruff]
  line-length = 120
  target-version = "py312"
  exclude = [
      "./src/buttercup/common/datastructures",
      "./src/buttercup/common/clusterfuzz_env",
      "./src/buttercup/common/clusterfuzz_parser",
      "src/buttercup/common/clusterfuzz_utils.py",
  ]
  
  [tool.ruff.lint]
  select = ["E", "F", "I", "W", "UP"]
  ignore = [
      "COM812", "ISC001",  # Formatter conflicts
  ]
  
  [tool.ruff.lint.per-file-ignores]
  "tests/**/*.py" = ["S101", "D"]  # Allow asserts, no docstrings in tests
  "*/__cli__.py" = ["T201"]  # Allow print in CLI modules
  "*/util_cli.py" = ["T201"]
  "*/challenge_task_cli.py" = ["T201"]
  "*/task_registry.py" = ["T201"]
  "src/buttercup/common/node_local.py" = ["UP040"]  # PEP 695 type aliases break runtime usage as constructors
  
  
  [tool.coverage.run]
  source = ["src/buttercup"]
  omit = ["*/tests/*", "*/__cli__.py", "*/_cli.py", "*/util_cli.py", "*/challenge_task_cli.py", "*/task_registry.py"]
  
  [tool.coverage.report]
  exclude_lines = [
      "pragma: no cover",
      "def __repr__",
      "if __name__ == .__main__.:",
      "raise NotImplementedError",
      "if TYPE_CHECKING:",
  ]
  
  [tool.mypy]
  plugins = ["pydantic.mypy"]
  mypy_path = "src"
  packages = "buttercup"
  allow_redefinition = true
  check_untyped_defs = true
  disallow_incomplete_defs = true
  disallow_untyped_defs = true
  ignore_missing_imports = true
  no_implicit_optional = true
  show_error_codes = true
  sqlite_cache = true
  strict_equality = true
  warn_no_return = true
  warn_redundant_casts = true
  warn_return_any = true
  warn_unreachable = true
  warn_unused_configs = true
  warn_unused_ignores = true
  exclude = [
      "src/buttercup/common/clusterfuzz_parser",
      "src/buttercup/common/clusterfuzz_env",
      "src/buttercup/common/clusterfuzz_utils",
      "src/buttercup/common/datastructures",
  ]
  