[build-system]
requires = ["poetry-core (>=2.0.0)", "poetry-dynamic-versioning (>=1.9.1,<2.0.0)"]
build-backend = "poetry_dynamic_versioning.backend"

[tool.poetry]
requires-poetry = ">=2.0.0"
packages = [ { include="CedarBackup3", from="src" } ]
include = [
   { path='Changelog', format='sdist' },
   { path='NOTICE', format='sdist' },
   { path='LICENSE', format='sdist' },
   { path='README.md', format='sdist' },
   { path='docs', format='sdist' },
   { path='manpages', format='sdist' },
   { path='samples', format='sdist' },
   { path='tests', format='sdist' },
]
classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Operating System :: OS Independent",
   "Environment :: Console",
   "Intended Audience :: System Administrators",
   "Natural Language :: English",
   "Topic :: Software Development :: Libraries",
   "Topic :: System :: Archiving :: Backup",
   "Topic :: Utilities",
]

[tool.poetry.requires-plugins]
poetry-dynamic-versioning = { version=">=1.5.2,<2.0.0", extras=["plugin"] }

# Published version is managed using Git tags
# We get either the tag (like "0.24.1") or a snapshot-type version (like "0.24.1+3.e8319c4")
[tool.poetry-dynamic-versioning]
enable = false
pattern = '^[vV](?P<base>\d+\.\d+\.\d+)'  # this extracts the version from our vX.Y.Z tag format
format-jinja = "{% if distance == 0 and not dirty %}{{ base }}{% else %}{{ base }}+{{ distance }}.{{ commit }}{% endif %}"

[project]
name = "cedar-backup3"
requires-python = ">=3.10,<4"
description = "Implements local and remote backups to CD/DVD and Amazon S3"
keywords = [ 'local', 'remote', 'backup', 'scp' ]
authors = [ { name="Kenneth J. Pronovici", email="pronovic@ieee.org" } ]
license = "GPL-2.0-only"
readme = "PyPI.md"
dynamic = [ "classifiers", ]
dependencies = [
   "chardet (>=5.2.0,<6.0.0)",  # Debian trixie has 5.2.0
]
version = "3.10.0"

[project.urls]
homepage = "https://pypi.org/project/cedar-backup3/"
repository = "https://github.com/pronovic/cedar-backup3"

[project.optional-dependencies]
docs = [
   "sphinx (>=8.1.3,<9.0.0)",              # Debian trixie has 8.1.3
   "sphinx-autoapi (>=3.3.3,<4.0.0)",      # Debian trixie has 3.3.3
]

[tool.poetry.group.dev.dependencies]
ruff = ">=0.12.10,<1.0.0"
coverage = ">=7.4.4,<8.0.0"
pre-commit = ">=4.0.1,<5.0.0"
colorama = ">=0.4.6,<1.0.0"

[tool.poetry.scripts]
cback3 = 'CedarBackup3.scripts:cback3' 
cback3-amazons3-sync = 'CedarBackup3.scripts:amazons3' 
cback3-span = 'CedarBackup3.scripts:span' 

[tool.coverage.paths]
source = [ "src" ]

[tool.coverage.run]
branch = true
source = [ "src/CedarBackup3" ]

[tool.coverage.report]
show_missing = false
precision = 1

[tool.ruff]
src = ["src"]
extend-exclude = [ "docs", "notes", ".poetry" ]
line-length = 132
preview = true

[tool.ruff.format]
quote-style = "double"
line-ending = "lf"
docstring-code-format = false

[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"

# Note: requires TID251 to be selected below
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pytest".msg = "use unittest, not pytest"

[tool.ruff.lint]
select = [
  # Start with all Ruff linter rules, and exclude some specific rules and categories (see below)
  "ALL"
]

ignore = [
  # Ruff-recommended exclusions, not needed because we're using the Ruff formatter
  "COM812",     # missing-trailing-comma
  "COM819",     # prohibited-trailing-comma
  "D206",       # docstring-tab-indentation
  "D300",       # triple-single-quotes
  "E111",       # indentation-with-invalid-multiple
  "E114",       # indentation-with-invalid-multiple-comment
  "E117",       # over-indented
  "E501",       # line-too-long
  "Q000",       # bad-quotes-inline-string
  "Q001",       # bad-quotes-multiline-string
  "Q002",       # bad-quotes-docstring
  "Q003",       # avoidable-escaped-quote
  "W191",       # tab-indentation

  # Exclusions of entire rule categories, standardized across all of my repos
  "C90",        # mccabe cyclomatic complexity
  "CPY",        # flake8-copyright
  "D",          # pydocstyle
  "DJ",         # flake8-django
  "DOC",        # pydoclint
  "EXE",        # flake8-executable
  "FIX",        # flake8-fixme
  "TD",         # flake8-todo

  # Exclusions of specific rules, standardized across all of my repos
  "ANN401",     # allow dynamically typed expressions using `typing.Any`
  "EM101",      # allow raw string messages in exceptions; having to pull out a variable makes code harder to read
  "EM102",      # allow f-string messages in exceptions; having to pull out a variable makes code harder to read
  "FURB140",    # don't automatically convert generator expressions to use `itertools.starmap()`
  "PGH004",     # allow `# noqa` with no error code; sometimes this is needed to prevent unwanted magical auto-fixes
  "PLR2004",    # allow magic numbers; using a constant doesn't necessarily make a magic number any more legible
  "PT011",      # allow `pytest.raises` for any exception type; this is often a false-positive that has little benefit
  "PT018",      # allow `assert` with multiple conditions; ruff suggestions often make the code less legible
  "PT019",      # allow unused PyTest fixtures; this check has a lot of false positives for `@unittest.mock.patch()`
  "S101",       # allow use of `assert`; we sometimes use assert as a type hint for MyPy, and do not run with -O
  "S404",       # allow use of `subprocess`; it's a common way to run shell commands, and this check is overly paranoid
  "SIM102",     # allow nested `if` clauses; ruff suggestions often make the code less legible
  "SIM117",     # allow nested `with` clauses; ruff suggestions often make the code less legible
  "TRY003",     # allow long messages in exceptions; this is often a false-positive that has little benefit

  # Exclusions of rule categories and specific rules, customized for this repository
  # Cedar Backup was first developed starting in 2002, long before many of these standards existed
  "ANN",        # don't require type annotations
  "B904",       # don't warn about raising from parent exception
  "BLE001",     # don't warn about catching blind exceptions
  "DTZ",        # ignore old-style datetime usage, such as of "naive" datetime objects
  "E722",       # don't warn about using bare except
  "ERA",        # eradicate does not understand the source tree's commenting style
  "FBT",        # allow positional boolean flags
  "FURB101",    # allow old-style open() and read() operations
  "FURB103",    # allow old-style open() and write() operations
  "FURB113",    # don't suggest use of list.extend() rather than repeated list.append()
  "FURB189",    # don't suggest subclassing collections.UserList instead of list
  "N",          # allow non-standard variable, function, & argument names, etc.
  "PERF",       # performance micro-optimizations are not worth much in this code
  "PLR0911",    # don't enforce rules about too many return statments
  "PLR0912",    # don't enforce rules about too many branches
  "PLR0913",    # don't enforce rules about too many arguments
  "PLR0914",    # don't enforce rules about too many variables
  "PLR0915",    # don't enforce rules about too many statements
  "PLR0916",    # don't enforce rules about too many boolean expressions
  "PLR0917",    # don't enforce rules about too many arguments
  "PLR1702",    # don't enforce rules about too many nested blocks
  "PLR5501",    # don't warn about elif instead of else/if
  "PLR6201",    # don't suggest using a set vs. a list when testing for membership
  "PLR6301",    # don't make recommendations about static methods
  "PLW1514",    # ignore open() without encoding; existing cross-platform behavior works but is fragile 
  "PLW1641",    # ignore __eq__ without __hash__; these objects work ok as-is and changing them is risky
  "PLW3201",    # ignore leftover __cmp__ methods from the original Python 2 implementation
  "PT",         # this codebase uses Unittest, so don't apply Pytest standards
  "PTH",        # allow old-style os operations rather than pathlib.Path
  "RET505",     # allow unnecessary else after return statement
  "RET506",     # allow unnecessary else after raise statement
  "RUF022",     # don't apply sorting standards for __all__
  "RUF055",     # ignore uses of the re module that can be replaced with builtin str methods
  "S110",       # don't warn about logging for try/except/pass blocks
  "SIM105",     # don't suggest use of contextlib.suppress(BaseException)
  "SIM108",     # don't suggest ternary operator instead of if/else block
  "SIM115",     # don't warn about using a context manager, since the code isn't designed for it
  "TRY",        # ignore all tryceratops warnings about exception anti-patterns
  "UP031",      # allow old-style format specifiers instead of f-strings
]

[tool.ruff.lint.per-file-ignores]
"tests/*" = [
  # Exclusions that apply to unit tests only, standardized across all of my repos
  "ANN",        # don't require type annotations in tests
  "FBT",        # allow use of boolean positional arguments
  "PLC1901",    # allow comparison to empty string
  "PLC2701",    # allow imports of private names
  "PLR",        # don't warn about too many arguments, methods, etc.
  "SLF001",     # allow access to private members

  # Exclusions of rule categories and specific rules, customized for this repository
  "PLC0415",    # allow import statements that are not at the top of the file
  "PLC2801",    # allow direct use of dunder methods like __str__
  "S108",       # don't warn about insecure temporary files
  "SIM201",     # don't suggest x != y instead of not x == y
  "SIM202",     # don't suggest x == y instead of not x != y
]
"src/CedarBackup3/tools/**/*" = [
  # Exclusions that apply to Cedar Backup tools only
  "T201",       # allow the print statement
]
