content: [build-system]
  build-backend = "setuptools.build_meta"
  requires = ["setuptools>=62.3"]
  
  [project]
  authors = [
    {name = "The Home Assistant Authors", email = "hello@home-assistant.io"},
  ]
  classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Intended Audience :: Developers",
    "Environment :: Console",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Topic :: Home Automation",
  ]
  dependencies = [
    "aiohttp",
    "aiorun",
    "coloredlogs",
    "orjson",
    "home-assistant-chip-clusters==2025.7.0",
  ]
  description = "Open Home Foundation Matter Server"
  license = {text = "Apache-2.0"}
  name = "python-matter-server"
  readme = "README.md"
  requires-python = ">=3.12"
  # The version is set by GH action on release!
  version = "0.0.0"
  
  [project.optional-dependencies]
  server = [
    "aiohttp==3.12.15",
    "aiorun==2025.1.1",
    "atomicwrites==1.4.1",
    "coloredlogs==15.0.1",
    "cryptography==46.0.2",
    "orjson==3.11.3",
    "zeroconf==0.148.0",
    "home-assistant-chip-core==2025.7.0",
  ]
  test = [
    "aioresponses==0.7.8",
    "codespell==2.4.1",
    "isort==6.1.0",
    "mypy==1.18.2",
    "pre-commit==4.3.0",
    "pre-commit-hooks==6.0.0",
    "pylint==3.3.9",
    "pytest==8.4.2",
    "pytest-asyncio==1.2.0",
    "pytest-aiohttp==1.1.0",
    "pytest-cov==7.0.0",
    "ruff==0.13.3",
    "tomli==2.2.1",
  ]
  
  [project.scripts]
  matter-server = "matter_server.server.__main__:main"
  
  [tool.codespell]
  ignore-words-list = "requestor"
  skip = "dashboard/package-lock.json,tests/fixtures/nodes/lighting-example-app.json,dashboard/src/client/models/descriptions.ts"
  
  [tool.setuptools]
  include-package-data = true
  platforms = ["any"]
  zip-safe = false
  
  [tool.setuptools.package-data]
  matter_server = ["py.typed", "dashboard/**"]
  
  [tool.setuptools.packages.find]
  include = ["matter_server*"]
  
  [tool.mypy]
  check_untyped_defs = true
  disallow_any_generics = false # TEMPORARY DISABLED
  disallow_incomplete_defs = true
  disallow_subclassing_any = true
  disallow_untyped_calls = true
  disallow_untyped_decorators = true
  disallow_untyped_defs = true
  follow_imports = "normal"
  ignore_missing_imports = true
  no_implicit_optional = true
  no_implicit_reexport = true
  platform = "linux"
  python_version = "3.11"
  strict_optional = true
  warn_incomplete_stub = true
  warn_no_return = true
  warn_redundant_casts = true
  warn_return_any = true
  warn_unreachable = true
  warn_unused_configs = true
  warn_unused_ignores = true
  
  [tool.pylint.MAIN]
  extension-pkg-allow-list = [
    "chip.*",
    "orjson",
  ]
  ignore-paths = [
    "scripts/beautify_diagnostics.py", # TEMPORARY DISABLED
    "scripts/generate_devices.py", # TEMPORARY DISABLED
  ]
  
  [tool.pylint.BASIC]
  good-names = [
    "_",
    "T",
  ]
  
  [tool.pylint.DESIGN]
  max-args = 10
  max-attributes = 12
  max-positional-arguments = 10
  
  [tool.pylint."MESSAGES CONTROL"]
  disable = [
    "duplicate-code", # unavoidable
    "format", # unavoidable
    "unsubscriptable-object", # unavoidable
    "unused-argument", # handled by ruff
    "unspecified-encoding", # handled by ruff
    "isinstance-second-argument-not-valid-type", # conflict with ruff
    "fixme", # we're still developing
    "too-few-public-methods", # unavoidable
  ]
  
  [tool.pylint.SIMILARITIES]
  ignore-imports = true
  
  [tool.pylint.FORMAT]
  max-line-length = 88
  
  [tool.pytest.ini_options]
  addopts = "--cov"
  asyncio_mode = "auto"
  
  [tool.ruff]
  fix = true
  line-length = 88
  show-fixes = true
  target-version = "py311"
  
  [tool.ruff.lint.pydocstyle]
  # Use Google-style docstrings.
  convention = "pep257"
  
  [tool.ruff.lint]
  ignore = [
    "ANN002", # Just annoying, not really useful
    "ANN003", # Just annoying, not really useful
    "ANN401", # Opinioated warning on disallowing dynamically typed expressions
    "D203", # Conflicts with other rules
    "D213", # Conflicts with other rules
    "D417", # False positives in some occasions
    "EM102", # Just annoying, not really useful
    "FIX002", # Just annoying, not really useful
    "PLR2004", # Just annoying, not really useful
    "PD011", # Just annoying, not really useful
    "S101", # assert is often used to satisfy type checking
    "TD002", # Just annoying, not really useful
    "TD003", # Just annoying, not really useful
    "TD004", # Just annoying, not really useful
    "COM812", # Conflict with the Ruff formatter
    "ISC001", # Conflict with the Ruff formatter
    # Quotes for typing.cast generally not necessary, only for performance critical paths
    "TC006", # Add quotes to type expression in typing.cast()
    "TID252", # TEMPORARY DISABLED
    "N805", # TEMPORARY DISABLED
    "EXE002", # TEMPORARY DISABLED
    "T201", # TEMPORARY DISABLED
    "ANN201", # TEMPORARY DISABLED
    "UP032", # TEMPORARY DISABLED
    "E711", # TEMPORARY DISABLED
    "E501", # TEMPORARY DISABLED
    "D104", # TEMPORARY DISABLED
    "B018", # TEMPORARY DISABLED
    "FBT003", # TEMPORARY DISABLED
    "PT012", # TEMPORARY DISABLED
    "UP007", # TEMPORARY DISABLED
    "D400", # TEMPORARY DISABLED
    "D204", # TEMPORARY DISABLED
    "PLW2901", # TEMPORARY DISABLED
    "RET507", # TEMPORARY DISABLED
    "INP001", # TEMPORARY DISABLED
    "ARG001", # TEMPORARY DISABLED
    "RUF006", # TEMPORARY DISABLED
    "SIM108", # TEMPORARY DISABLED
    "ANN001", # TEMPORARY DISABLED
    "SIM117", # TEMPORARY DISABLED
    "TRY003", # TEMPORARY DISABLED
    "UP037", # TEMPORARY DISABLED
    "UP006", # TEMPORARY DISABLED
    "UP041", # TEMPORARY DISABLED
    "D202", # TEMPORARY DISABLED
    "FBT002", # TEMPORARY DISABLED
    "FBT001", # TEMPORARY DISABLED
    "PTH123", # TEMPORARY DISABLED
    "ANN204", # TEMPORARY DISABLED
    "EM102", # TEMPORARY DISABLED
    "PLR0915", # TEMPORARY DISABLED
    "EM101", # TEMPORARY DISABLED
    "EM102", # TEMPORARY DISABLED
    "ERA001", # TEMPORARY DISABLED
    "PYI036", # TEMPORARY DISABLED
    "ANN204", # TEMPORARY DISABLED
    "N818", # TEMPORARY DISABLED
    "N815", # TEMPORARY DISABLED
    "N801", # TEMPORARY DISABLED
    "N813", # TEMPORARY DISABLED
    "RUF012", # TEMPORARY DISABLED
    "B007", # TEMPORARY DISABLED
    "SIM102", # TEMPORARY DISABLED
    "C901", # TEMPORARY DISABLED
    "PLR0911", # TEMPORARY DISABLED
    "PLR0912", # TEMPORARY DISABLED
    "SLF001", # TEMPORARY DISABLED
    "RUF010", # TEMPORARY DISABLED
    "TRY300", # TEMPORARY DISABLED
    "UP038", # TEMPORARY DISABLED
    "PTH118", # TEMPORARY DISABLED
    "PTH112", # TEMPORARY DISABLED
    "PTH102", # TEMPORARY DISABLED
    "TRY400", # TEMPORARY DISABLED
    "DTZ001", # TEMPORARY DISABLED
    "TRY201", # TEMPORARY DISABLED
    "A002", # TEMPORARY DISABLED
    "DTZ003", # TEMPORARY DISABLED
    "N803", # TEMPORARY DISABLED
    "ARG002", # TEMPORARY DISABLED
    "S104", # TEMPORARY DISABLED
    "UP015", # TEMPORARY DISABLED
  ]
  
  select = ["ALL"]
  
  [tool.ruff.lint.flake8-builtins]
  builtins-allowed-modules = ["json"]
  
  [tool.ruff.lint.flake8-pytest-style]
  fixture-parentheses = false
  mark-parentheses = false
  
  [tool.ruff.lint.isort]
  combine-as-imports = true
  force-sort-within-sections = true
  known-first-party = ["matter_server"]
  
  [tool.ruff.lint.mccabe]
  max-complexity = 25
  
  [tool.ruff.lint.pylint]
  max-args = 10
  max-branches = 25
  max-returns = 15
  max-statements = 50
  