content: [project]
  name = "stack-pr"
  authors = [
      {name = "Modular Inc", email = "hello@modular.com"},
  ]
  maintainers = [
      {name = "Modular Inc", email = "hello@modular.com"}
  ]
  description = "Stacked PR CLI for Github"
  readme = "README.md"
  license = { file = "LICENSE" }
  requires-python = ">=3.9"
  keywords = ["stacked-prs", "github", "pull-requests", "stack-pr", "git", "version-control"]
  classifiers = [
      "Development Status :: 5 - Production/Stable",
      "Intended Audience :: Developers",
      "Topic :: Software Development :: Version Control :: Git",
      "License :: OSI Approved :: Apache Software License",
      "Operating System :: OS Independent",
      "Environment :: Console",
      "Topic :: Utilities",
      "Programming Language :: Python",
      "Programming Language :: Python :: 3.9",
      "Programming Language :: Python :: 3.10",
      "Programming Language :: Python :: 3.11",
      "Programming Language :: Python :: 3.12",
      "Programming Language :: Python :: 3.13",
  ]
  # Version is dynamically set by pdm by the SCM version
  dynamic = ["version"]
  dependencies = ["typing_extensions; python_version<\"3.13\""]
  
  [project.optional-dependencies]
  dev = [
      "pytest",
      "pytest-mock",
      "mypy",
      "ruff",
  ]
  
  [project.urls]
  Homepage = "https://github.com/modular/stack-pr"
  Repository = "https://github.com/modular/stack-pr"
  "Bug Tracker" = "https://github.com/modular/stack-pr/issues"
  
  [project.scripts]
  stack-pr = "stack_pr.cli:main"
  
  [build-system]
  requires = ["pdm-backend"]
  build-backend = "pdm.backend"
  
  [tool.pdm]
  distribution = true
  
  [tool.pdm.version]
  source = "scm"
  fallback_version = "0.1.0"
  
  [tool.pixi.project]
  channels = ["conda-forge"]
  platforms = ["osx-arm64", "osx-64", "linux-64", "linux-aarch64"]
  
  [tool.pixi.pypi-dependencies]
  stack-pr = { path = ".", editable = true }
  pdm = ">=2.17.1,<2.18"
  
  [tool.pixi.tasks]
  
  [tool.pixi.dependencies]
  python = "3.9.*"
  
  [tool.ruff]
  
  # Same as Black.
  line-length = 88
  
  # Assume Python 3.9
  target-version = "py39"
  
  [tool.ruff.lint]
  # Enable pycodestyle (`E`), Pyflakes (`F`), and isort (`I`) codes
  select = [
      "E",   # pycodestyle errors
      "F",   # pyflakes
      "I",   # isort
      "B",   # flake8-bugbear
      "C4",  # flake8-comprehensions
      "UP",  # pyupgrade
      "N",   # pep8-naming
      "SIM", # flake8-simplify
      "RUF", # ruff-specific rules
      "W",   # pycodestyle warnings
      "YTT", # flake8-2020
      "ANN", # flake8-annotations
      "S",   # flake8-bandit
      "BLE", # flake8-blind-except
      "FBT", # flake8-boolean-trap
      "A",   # flake8-builtins
      "C",   # flake8-comprehensions
      "DTZ", # flake8-datetimez
      "T10", # flake8-debugger
      "ISC", # flake8-implicit-str-concat
      "G",   # flake8-logging-format
      "INP", # flake8-no-pep420
      "PIE", # flake8-pie
      "T20", # flake8-print
      "PT",  # flake8-pytest-style
      "Q",   # flake8-quotes
      "RSE", # flake8-raise
      "RET", # flake8-return
      "SLF", # flake8-self
      "TID", # flake8-tidy-imports
      "ARG", # flake8-unused-arguments
      "PTH", # flake8-use-pathlib
      "ERA", # eradicate
      "PD",  # pandas-vet
      "PGH", # pygrep-hooks
      "PL",  # pylint
      "TRY", # tryceratops
      "FA100", #future-rewritable-type-annotation
      "PYI036", # bad-exit-annotation
      # "COM812", # trailing-comma (this one makes ruff formater mad)
  ]
  
  # Ignore specific rules
  ignore = [
      # This is just too complex to do anything about when invoking gh suprocess.
      "S603",  # subprocess call with untrusted input
  
      # We use some of the strings for output in the CLI and want specific formatting.
      "TRY003", # Avoid specifying long messages outside exception class
  
      # We forward kwargs a lot and ruff doesn't like it. (more than 5)
      "PLR0913", # Too many arguments
  
      # FIXME: We use print statements in the CLI instead of stderr/stdout (this may change)
      "T201", # allow print statements
  
      # FIXME: Some of our strings are long for CLI output. We should refactor them.
      "E501", # Line too long
  ]
  
  # Borrowing a rustism and allow unused variables when underscore-prefixed.
  dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
  
  [tool.ruff.lint.isort]
  known-first-party = ["stack_pr"]
  
  [tool.ruff.lint.mccabe]
  # Unlike Flake8, default to a complexity level of 16.
  max-complexity = 16
  
  [tool.ruff.lint.per-file-ignores]
  # Ignore unused imports in __init__.py files
  "__init__.py" = ["F401"]
  
  [tool.ruff.lint.pydocstyle]
  convention = "google"
  
  [tool.ruff.lint.pycodestyle]
  max-doc-length = 88
  
  [tool.ruff.lint.flake8-quotes]
  docstring-quotes = "double"
  inline-quotes = "double"
  multiline-quotes = "double"
  
  [tool.ruff.lint.extend-per-file-ignores]
  # Allow certain useful patterns in tests
  "tests/**/*.py" = [
      "S101", # allow assert statements within if statements
      "ARG", # allow unused arguments
      "FBT", # allow boolean traps
      "ANN401", # allow Any in tests
      "T201", # allow print statements in tests
      "PLR2004", # allow magic value comparisons in tests
  ]
  
  [tool.pytest.ini_options]
  asyncio_mode = "auto"
  asyncio_default_fixture_loop_scope = "function"
  testpaths = ["tests"]
  python_files = ["test_*.py"]
  addopts = "-v"
  
  [tool.mypy]
  # Let's be strict.
  python_version = "3.9"
  warn_return_any = true
  warn_unused_configs = true
  disallow_untyped_defs = true
  disallow_incomplete_defs = true
  check_untyped_defs = true
  disallow_untyped_decorators = true
  no_implicit_optional = true
  warn_redundant_casts = true
  warn_unused_ignores = true
  warn_no_return = true
  warn_unreachable = true
  strict_optional = true
  