content: [build-system]
  requires = ["setuptools"]
  build-backend = "setuptools.build_meta"
  
  
  [tool.towncrier]
  directory = "changes"
  package = "ckan"
  filename = "CHANGELOG.rst"
  title_format = "v.{version} {project_date}"
  issue_format = "`#{issue} <https://github.com/ckan/ckan/pull/{issue}>`_"
  wrap = true
  
  [[tool.towncrier.type]]
  directory = 'migration'
  name = 'Migration notes'
  showcontent = true
  
  [[tool.towncrier.type]]
  directory = 'feature'
  name = 'Major features'
  showcontent = true
  
  [[tool.towncrier.type]]
  directory = 'misc'
  name = 'Minor changes'
  showcontent = true
  
  [[tool.towncrier.type]]
  directory = 'bugfix'
  name = 'Bugfixes'
  showcontent = true
  
  [[tool.towncrier.type]]
  directory = 'removal'
  name = 'Removals and deprecations'
  showcontent = true
  
  [tool.black]
  line-length = 79
  preview = true
  
  [tool.pytest.ini_options]
  retries = 0
  retry_delay = 0.5
  cumulative_timing = true
  filterwarnings = [
      "ignore::DeprecationWarning",
      "ignore::bs4.GuessedAtParserWarning",  # using lxml as default parser
      "error::sqlalchemy.exc.RemovedIn20Warning",
  ]
  markers = [
      "ckan_config: patch configuration used by other fixtures via (key, value) pair.",
  ]
  
  testpaths = ["ckan", "ckanext"]
  addopts = "--strict-markers --pdbcls=IPython.terminal.debugger:TerminalPdb --ckan-ini=test-core.ini"
  
  [tool.pyright]
  pythonVersion = "3.9"
  include = ["ckan", "ckanext"]
  exclude = [
      "**/test*",
      "**/migration",
      "ckan/lib/create_test_data.py"
  ]
  strict = []
  
  strictParameterNoneValue = true # type must be Optional if default value is None
  
  # Check the meaning of rules here
  # https://github.com/microsoft/pyright/blob/main/docs/configuration.md
  reportFunctionMemberAccess = true # non-standard member accesses for functions
  reportMissingImports = true
  reportMissingModuleSource = true
  reportMissingTypeStubs = false
  reportImportCycles = false
  reportUnusedImport = true
  reportUnusedClass = true
  reportUnusedFunction = true
  reportUnusedVariable = true
  reportDuplicateImport = true
  reportOptionalSubscript = true
  reportOptionalMemberAccess = true
  reportOptionalCall = true
  reportOptionalIterable = true
  reportOptionalContextManager = true
  reportOptionalOperand = true
  # We are using Context in a way that conflicts with this check
  reportTypedDictNotRequiredAccess = false
  reportConstantRedefinition = true
  reportIncompatibleMethodOverride = false
  reportIncompatibleVariableOverride = false
  reportOverlappingOverload = true
  reportUntypedFunctionDecorator = false
  reportUnknownParameterType = true
  reportUnknownArgumentType = false
  reportUnknownLambdaType = false
  reportUnknownMemberType = false
  reportMissingTypeArgument = true
  reportInvalidTypeVarUse = true
  reportCallInDefaultInitializer = true
  reportUnknownVariableType = false
  reportUntypedBaseClass = true
  reportUnnecessaryIsInstance = true
  reportUnnecessaryCast = true
  reportUnnecessaryComparison = true
  reportAssertAlwaysTrue = true
  reportSelfClsParameterName = true
  reportUnusedCallResult = false # allow function calls for side-effect only (like logic.check_acces)
  useLibraryCodeForTypes = true
  reportGeneralTypeIssues = true
  reportPropertyTypeMismatch = true
  reportWildcardImportFromLibrary = true
  reportUntypedClassDecorator = false # authenticator relies on repoze.who class-decorator
  reportUntypedNamedTuple = true
  reportPrivateUsage = false # TODO: do not access private members in CKAN's codebase
  reportPrivateImportUsage = true
  reportInconsistentConstructor = true
  reportMissingSuperCall = false
  reportUninitializedInstanceVariable = false
  reportInvalidStringEscapeSequence = true
  reportMissingParameterType = true
  reportImplicitStringConcatenation = false
  reportUndefinedVariable = true
  reportUnboundVariable = true
  reportInvalidStubStatement = true
  reportIncompleteStub = true
  reportUnsupportedDunderAll = true
  reportUnusedCoroutine = true
  reportUnnecessaryTypeIgnoreComment = true
  reportMatchNotExhaustive = true
  
  [tool.mypy]
  plugins = "sqlalchemy.ext.mypy.plugin"
  files = "ckan"
  exclude = "ckan/(pastertemplates|tests|migration)"
  
  [[tool.mypy.overrides]]
  ignore_missing_imports = true
  module = [
      "babel.*",
      "blinker.*",
      "cookiecutter.*",
      "dominate.*",
      "feedgen.*",
      "flask_babel.*",
      "flask_debugtoolbar.*",
      "flask_multistatic.*",
      "passlib.*",
      "pysolr.*",
      "repoze.*",
      "rq.*",
      "webassets.*",
      "zope.*",
  ]
  
  [tool.ruff]
  extend-exclude = [
      "./src",
  ]
  
  # Allow lines to be as long as 120 characters.
  line-length = 120
  
  [tool.ruff.lint]
  select = [
      "E",
      "F",
      "Q",
      "INP001", # Checks for packages that are missing an __init__.py file.
  ]
  extend-ignore = [
      "Q003", # avoidable-escaped-quote
      "E712", # true-false-comparison (interferes with sqlAlchemy queries)
  ]
  
  [tool.ruff.lint.flake8-quotes]
  inline-quotes = "single"
  multiline-quotes = "single"
  
  [tool.ruff.format]
  # Prefer single quotes over double quotes
  quote-style = "single"
  