content: 
  [build-system]
  build-backend = "hatchling.build"
  requires = ["hatch-fancy-pypi-readme==25.1.0", "hatchling==1.27.0"]
  
  [project]
  authors = [{ name = "MountainGod2", email = "admin@reid.ca" }]
  classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Typing :: Typed",
  ]
  dependencies = [
    "backoff==2.2.1",
    "httpx==0.28.1",
    "pydantic==2.11.9",
    "python-dotenv==1.1.1",
    "rich-click==1.9.1",
    "rich==14.1.0",
  ]
  description = "Python library for interacting with the Chaturbate Events API"
  dynamic = ["readme"]
  keywords = ["api", "chaturbate", "poller", "python"]
  license = "MIT"
  license-files = ["LICEN[CS]E*"]
  name = "chaturbate-poller"
  requires-python = ">=3.12"
  scripts = { chaturbate_poller = "chaturbate_poller.__main__:cli" }
  urls.changelog = "https://github.com/MountainGod2/chaturbate_poller/blob/main/CHANGELOG.md"
  urls.documentation = "https://mountaingod2.github.io/chaturbate_poller/"
  urls.homepage = "https://github.com/MountainGod2/chaturbate_poller"
  urls.issues = "https://github.com/MountainGod2/chaturbate_poller/issues"
  urls.repository = "https://github.com/MountainGod2/chaturbate_poller"
  version = "5.1.8"
  
  [dependency-groups]
  build = ["python-semantic-release==10.4.1", "uv==0.8.22"]
  dev = [
    "bandit-sarif-formatter==1.1.1",
    "bandit==1.8.6",
    "basedpyright==1.31.5",
    "mypy==1.18.2",
    "pip-audit==2.9.0",
    "pre-commit==4.3.0",
    "pylint==3.3.8",
    "pytest-asyncio==1.2.0",
    "pytest-cov==7.0.0",
    "pytest-mock==3.15.1",
    "pytest-timeout==2.4.0",
    "pytest-xdist==3.8.0",
    "pytest==8.4.2",
    "python-semantic-release==10.4.1",
    "respx==0.22.0",
    "ruff==0.13.2",
  ]
  docs = [
    "furo==2025.9.25",
    "myst-nb==1.3.0",
    "sphinx-autoapi==3.6.0",
    "sphinx-autodoc-typehints==3.2.0",
    "sphinx-copybutton==0.5.2",
    "sphinx-design==0.6.1",
    "sphinx==8.2.3",
  ]
  
  [tool.hatch]
  build.targets.wheel.packages = ["src/chaturbate_poller"]
  metadata.hooks.fancy-pypi-readme.content-type = "text/markdown"
  
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Features"
  path = "README.md"
  start-at = "# Chaturbate Poller"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Installation"
  path = "README.md"
  start-at = "## Features"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Usage"
  path = "README.md"
  start-at = "## Installation"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Development"
  path = "README.md"
  start-at = "## Usage"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Documentation"
  path = "README.md"
  start-at = "## Development"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## Contributing"
  path = "README.md"
  start-at = "## Documentation"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  end-before = "## License"
  path = "README.md"
  start-at = "## Contributing"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
  path = "README.md"
  start-at = "## License"
  
  [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
  # Replace relative links to the GitHub repository with absolute links.
  pattern = '\[(.+?)\]\(((?!https?://)\.?/?(\S+?))\)'
  replacement = '[\1](https://github.com/MountainGod2/chaturbate_poller/tree/main/\g<3>)'
  
  [tool.pylint]
  fail-under = 8.0
  ignore-paths = [".venv", "build", "dist", "docs", "examples", "out", "tests"]
  typecheck.signature-mutators = [
    "click.decorators.argument",
    "click.decorators.confirmation_option",
    "click.decorators.help_option",
    "click.decorators.option",
    "click.decorators.pass_context",
    "click.decorators.version_option",
  ]
  
  [tool.semantic_release]
  branch = "main"
  build_command = """
    uv lock --offline
    uv build
  """
  changelog_file = "CHANGELOG.md"
  version_toml = ["pyproject.toml:project.version"]
  
  [tool.coverage]
  omit = ["**/__init__.py", "examples/*", "tests/*"]
  report.exclude_lines = [
    "def __repr__",
    "from __future__ import annotations",
    "if TYPE_CHECKING:",
    "if __name__ == '__main__':",
    "if typing.TYPE_CHECKING:",
    "pragma: no cover",
    "raise NotImplementedError",
  ]
  report.fail_under = 90
  report.show_missing = true
  report.skip_covered = true
  run.branch = true
  source = ["src/chaturbate_poller"]
  
  [tool.pytest.ini_options]
  addopts = [
    "--cov-fail-under=80",
    "--cov-report=html",
    "--cov-report=term-missing",
    "--cov-report=xml",
    "--cov=src/chaturbate_poller",
    "--strict-config",
    "--strict-markers",
    "--tb=short",
    "--timeout=300",
    "--verbose",
  ]
  asyncio_default_fixture_loop_scope = "function"
  asyncio_mode = "auto"
  python_classes = ["Test*"]
  python_files = ["test_*.py"]
  python_functions = ["test_*"]
  testpaths = ["tests"]
  
  [tool.autopep8]
  aggressive = 3
  in-place = true
  max_line_length = 100
  recursive = true
  
  [tool.ruff]
  extend-include = ["*.pyw"]
  fix = true
  format.docstring-code-format = true
  format.docstring-code-line-length = "dynamic"
  format.indent-style = "space"
  format.line-ending = "auto"
  format.preview = true
  format.quote-style = "double"
  format.skip-magic-trailing-comma = false
  line-length = 100
  lint.fixable = ["ALL"]
  lint.ignore = [
    "COM812",
    "CPY001", # Per file copyright notice
    "D203",
    "D213",   # Docs-related
    "INP001",
    "ISC001", # Examples-related
  ]
  lint.per-file-ignores."docs/*" = [
    "ANN001",
    "ANN201",
    "D100",
    "D103",
    "PLE1142",
    "T201",
  ]
  lint.per-file-ignores."examples/*" = [
    #   "ANN001",
    #   "ANN201",
    "D100",
    "D103",
    #   "T201",
  ]
  lint.per-file-ignores."out/*" = ["ALL"]
  lint.per-file-ignores."tests/*" = [
    "ANN401",
    "D100",
    "FBT001",
    "PLR0913",
    "PLR2004",
    "PLR6301",
    "S101",
    "SIM117",
    "SLF001",
  ]
  lint.pydocstyle.convention = "google"
  lint.select = ["ALL"]
  lint.unfixable = []
  target-version = "py313"
  
  [tool.mypy]
  check_untyped_defs = true
  disallow_any_unimported = true
  disallow_untyped_defs = true
  exclude = ["examples"]
  no_implicit_optional = true
  plugins = ["pydantic.mypy"]
  python_version = "3.13"
  show_error_codes = true
  strict = true
  warn_return_any = true
  warn_unused_configs = true
  warn_unused_ignores = false
  
  [tool.pydantic-mypy]
  init_typed = true
  warn_required_dynamic_aliases = true
  
  [tool.bandit]
  exclude_dirs = [".venv", "tests"]
  
  [tool.basedpyright]
  defineConstant = { DEBUG = true }
  exclude = [
    "**/__pycache__",
    "**/node_modules",
    ".venv",
    "build",
    "dist",
    "docs",
    "examples",
    "out",
    "src/typestubs",
    "tests",
  ]
  include = ["src"]
  pythonVersion = "3.13"
  reportAny = false
  reportImplicitOverride = false
  reportPrivateImportUsage = false
  reportUnnecessaryTypeIgnoreComment = false
  reportUnusedCallResult = false
  