content: [build-system]
  requires = ["hatchling", "versioningit"]
  build-backend = "hatchling.build"
  
  [project]
  name = "dispatch"
  dynamic = ["version"]
  description = "Dispatch is a incident management and orchestration platform"
  readme = "README.md"
  license = {text = "Apache-2.0"}
  authors = [
      {name = "Netflix, Inc.", email = "oss@netflix.com"}
  ]
  maintainers = [
      {name = "Netflix OSS", email = "oss@netflix.com"}
  ]
  requires-python = ">=3.11"
  classifiers = [
      "Development Status :: 5 - Production/Stable",
      "Intended Audience :: Developers",
      "Programming Language :: Python :: 3.11",
      "Programming Language :: Python :: 3.12",
      "Programming Language :: Python :: 3.13",
      "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
      "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
      "Topic :: Software Development :: Libraries :: Python Modules",
      "Topic :: System :: Systems Administration",
  ]
  keywords = ["incident", "management", "orchestration", "response", "security"]
  
  dependencies = [
      "aiocache",
      "aiofiles",
      "aiohttp",
      "alembic",
      "atlassian-python-api",
      "attrs>=22.2.0",
      "bcrypt",
      "blockkit==1.9.2",
      "boto3",
      "cachetools",
      "chardet",
      "click",
      "cryptography<42,>=38.0.0",
      "duo-client",
      "email-validator",
      "emails",
      "fastapi==0.115.12",
      "google-api-python-client",
      "google-auth-oauthlib",
      "h11",
      "httpx",
      "jinja2",
      "jira",
      "joblib",
      "jsonpath_ng",
      "lxml==5.3.0",
      "markdown",
      "msal",
      "numpy",
      "oauth2client",
      "openai==1.77.0",
      "pandas",
      "pdpyras",
      "protobuf<5.0dev,>=4.21.6",
      "psycopg2-binary",
      "pyarrow",
      "pydantic==2.11.4",
      "pydantic-extra-types==2.10.4",
      "pyparsing",
      "python-dateutil",
      "python-jose",
      "python-multipart",
      "python-slugify",
      "pytz",
      "requests",
      "schedule",
      "schemathesis",
      "sentry-asgi",
      "sentry-sdk==1.45.0",
      "sh",
      "slack-bolt",
      "slack_sdk",
      "slowapi",
      "spacy==3.8.7",
      "sqlalchemy-filters",
      "sqlalchemy-utils",
      "sqlalchemy==2.0.8",
      "statsmodels",
      "tabulate",
      "tenacity",
      "thinc==8.3.4",
      "tiktoken",
      "typing-extensions==4.13.2",
      "uvicorn",
      "uvloop",
      "validators==0.18.2",
  ]
  
  [project.optional-dependencies]
  dev = [
      "attrs>=22.2.0",
      "black",
      "click",
      "coverage",
      "devtools",
      "easydict",
      "factory-boy",
      "faker",
      "ipython",
      "pre-commit",
      "pytest==7.4.4",
      "pytest-mock",
      "ruff",
      "typing-extensions==4.13.2",
  ]
  netflix = [
      "dispatch-internal-plugins",
  ]
  
  [project.scripts]
  dispatch = "dispatch.cli:entrypoint"
  
  [project.entry-points."dispatch.plugins"]
  dispatch_atlassian_confluence = "dispatch.plugins.dispatch_atlassian_confluence.plugin:ConfluencePagePlugin"
  dispatch_atlassian_confluence_document = "dispatch.plugins.dispatch_atlassian_confluence.docs.plugin:ConfluencePageDocPlugin"
  dispatch_auth_mfa = "dispatch.plugins.dispatch_core.plugin:DispatchMfaPlugin"
  dispatch_aws_alb_auth = "dispatch.plugins.dispatch_core.plugin:AwsAlbAuthProviderPlugin"
  dispatch_aws_sqs = "dispatch.plugins.dispatch_aws.plugin:AWSSQSSignalConsumerPlugin"
  dispatch_basic_auth = "dispatch.plugins.dispatch_core.plugin:BasicAuthProviderPlugin"
  dispatch_contact = "dispatch.plugins.dispatch_core.plugin:DispatchContactPlugin"
  dispatch_header_auth = "dispatch.plugins.dispatch_core.plugin:HeaderAuthProviderPlugin"
  dispatch_participant_resolver = "dispatch.plugins.dispatch_core.plugin:DispatchParticipantResolverPlugin"
  dispatch_pkce_auth = "dispatch.plugins.dispatch_core.plugin:PKCEAuthProviderPlugin"
  dispatch_ticket = "dispatch.plugins.dispatch_core.plugin:DispatchTicketPlugin"
  duo_auth_mfa = "dispatch.plugins.dispatch_duo.plugin:DuoMfaPlugin"
  generic_workflow = "dispatch.plugins.generic_workflow.plugin:GenericWorkflowPlugin"
  github_monitor = "dispatch.plugins.dispatch_github.plugin:GithubMonitorPlugin"
  google_calendar_conference = "dispatch.plugins.dispatch_google.calendar.plugin:GoogleCalendarConferencePlugin"
  google_docs_document = "dispatch.plugins.dispatch_google.docs.plugin:GoogleDocsDocumentPlugin"
  google_drive_storage = "dispatch.plugins.dispatch_google.drive.plugin:GoogleDriveStoragePlugin"
  google_drive_task = "dispatch.plugins.dispatch_google.drive.plugin:GoogleDriveTaskPlugin"
  google_gmail_email = "dispatch.plugins.dispatch_google.gmail.plugin:GoogleGmailEmailPlugin"
  google_groups_participants = "dispatch.plugins.dispatch_google.groups.plugin:GoogleGroupParticipantGroupPlugin"
  jira_ticket = "dispatch.plugins.dispatch_jira.plugin:JiraTicketPlugin"
  microsoft_teams_conference = "dispatch.plugins.dispatch_microsoft_teams.conference.plugin:MicrosoftTeamsConferencePlugin"
  openai_artificial_intelligence = "dispatch.plugins.dispatch_openai.plugin:OpenAIPlugin"
  opsgenie_oncall = "dispatch.plugins.dispatch_opsgenie.plugin:OpsGenieOncallPlugin"
  pagerduty_oncall = "dispatch.plugins.dispatch_pagerduty.plugin:PagerDutyOncallPlugin"
  slack_contact = "dispatch.plugins.dispatch_slack.plugin:SlackContactPlugin"
  slack_conversation = "dispatch.plugins.dispatch_slack.plugin:SlackConversationPlugin"
  zoom_conference = "dispatch.plugins.dispatch_zoom.plugin:ZoomConferencePlugin"
  
  [project.urls]
  Homepage = "https://dispatch.io"
  Documentation = "https://dispatch.io/docs"
  Repository = "https://github.com/netflix/dispatch"
  Issues = "https://github.com/netflix/dispatch/issues"
  Changelog = "https://github.com/netflix/dispatch/releases"
  
  [tool.hatch.version]
  source = "versioningit"
  
  [tool.hatch.metadata]
  allow-direct-references = true
  
  [tool.hatch.build]
  packages = ["src/dispatch"]
  include = [
      "/src/dispatch/static/**/*",
      "/src/dispatch/**/*.py",
  ]
  
  [tool.hatch.build.targets.wheel]
  packages = ["src/dispatch"]
  
  [tool.hatch.build.targets.sdist]
  include = [
      "/src/dispatch",
      "/tests",
      "/src/dispatch/static/**/*",
      "README.md",
      "LICENSE",
  ]
  
  [tool.versioningit]
  default-version = "0.1.0"
  
  [tool.versioningit.vcs]
  method = "git"
  match = ["v*"]
  
  [tool.versioningit.format]
  distance = "{base_version}.{distance}+{vcs}{rev}"
  dirty = "{base_version}.{distance}+d{build_date:%Y%m%d}"
  distance-dirty = "{base_version}.{distance}+{vcs}{rev}.d{build_date:%Y%m%d}"
  
  [tool.pytest.ini_options]
  python_files = ["test*.py"]
  addopts = [
      "--tb=native",
      "-p", "no:doctest",
      "-p", "no:warnings"
  ]
  norecursedirs = ["bin", "dist", "docs", "htmlcov", "script", "hooks", "node_modules", ".*"]
  testpaths = ["tests"]
  
  [tool.coverage.run]
  source = ["src", "tests"]
  omit = ["dispatch/migrations/*"]
  
  [tool.coverage.report]
  exclude_lines = [
      "pragma: no cover",
      "def __repr__",
      "raise AssertionError",
      "raise NotImplementedError",
      "if __name__ == .__main__.:",
      "if TYPE_CHECKING:",
  ]
  
  [tool.black]
  line-length = 100
  target-version = ['py311']
  include = '\.pyi?$'
  
  [tool.ruff]
  # Exclude a variety of commonly ignored directories.
  exclude = [
      ".bzr",
      ".direnv",
      ".eggs",
      ".git",
      ".hg",
      ".mypy_cache",
      ".nox",
      ".pants.d",
      ".ruff_cache",
      ".svn",
      ".tox",
      ".venv",
      "__pypackages__",
      "_build",
      "buck-out",
      "build",
      "dist",
      "node_modules",
      "venv",
  ]
  
  # Same as Black.
  line-length = 100
  
  # Assume Python 3.11
  target-version = "py311"
  
  [tool.ruff.lint]
  select = [
      "E",  # pycodestyle errors
      "W",  # pycodestyle warnings
      "F",  # pyflakes
      # "I",  # isort
      "C",  # flake8-comprehensions
      "B",  # flake8-bugbear
  ]
  ignore = [
      "E501",  # line too long, handled by black
      "B008",  # do not perform function calls in argument defaults
      "C901",  # complexity
  ]
  
  # Allow autofix for all enabled rules (when `--fix`) is provided.
  fixable = ["A", "B", "C", "D", "E", "F"]
  unfixable = []
  
  # Allow unused variables when underscore-prefixed.
  dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
  
  [tool.ruff.lint.mccabe]
  # Unlike Flake8, default to a complexity level of 10.
  max-complexity = 10
  
  [tool.ruff.lint.isort]
  known-third-party = ["fastapi", "pydantic", "starlette"]
  
  [tool.ruff.lint.per-file-ignores]
  "tests/conftest.py" = ["E402"]
  "src/dispatch/entity/service.py" = ["W605"]
  
  [dependency-groups]
  netflix = [
      "dispatch-internal-plugins",
  ]
  
  [tool.uv.sources]
  dispatch-internal-plugins = { path = "../dispatch-internal-plugins", editable = true }
  