[project]
name = "borgmatic"
version = "2.0.10"
authors = [
  { name="Dan Helfman", email="witten@torsion.org" },
]
description = "Simple, configuration-driven backup software for servers and workstations"
readme = "README.md"
requires-python = ">=3.9"
classifiers=[
    "Development Status :: 5 - Production/Stable",
    "Environment :: Console",
    "Intended Audience :: System Administrators",
    "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
    "Programming Language :: Python",
    "Topic :: Security :: Cryptography",
    "Topic :: System :: Archiving :: Backup",
]
dependencies = [
    "jsonschema",
    "packaging",
    "requests",
    "ruamel.yaml>0.15.0",
]

[project.scripts]
borgmatic = "borgmatic.commands.borgmatic:main"
generate-borgmatic-config = "borgmatic.commands.generate_config:main"
validate-borgmatic-config = "borgmatic.commands.validate_config:main"

[project.optional-dependencies]
Apprise = ["apprise"]

[project.urls]
Homepage = "https://torsion.org/borgmatic"

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools.packages.find]
include = ["borgmatic*"]
namespaces = false

[tool.pytest.ini_options]
testpaths = "tests"
addopts = "--cov-report term-missing:skip-covered --cov=borgmatic --no-cov-on-fail --cov-fail-under=100 --ignore=tests/end-to-end"

[tool.ruff]
line-length = 100
exclude = ["*.*/*"]

[tool.ruff.format]
quote-style = "preserve"

[tool.ruff.lint]
preview = true
extend-select = [
    "A",  # flake8-builtins: builtin shadowing
    "B",  # flake8-bugbear: bugs and design problems
    "BLE",  # flak8-blind-except: "except:" without exception type
    "C4",  # flake8-comprehensions: generators and comprehensions
    "COM",  # flake8-commas: trailing commas
    "DTZ",  # flake8-datetimez: naive datetime
    "E",  # pycodestyle: errors
    "F",  # pyflakes: various linting
    "ERA",  # eradicate: find commented out code
    "FLY",  # flynt: f-string instead of string join
    "FIX",  # flake8-fixme: leftover FIXMEs and TODOs
    "I",  # isort: import ordering
    "ISC",  # flake8-implicit-str-concat: implicit string concatenation
    "LOG",  # flake8-logging: standard library logging
    "N",  # pep8-naming: PEP-8 naming conventions
    "PERF",  # perflint: performance linting
    "PIE",  # flake8-pie: various linting
    "PL",  # pylint: various linting
    "Q",  # flake8-quotes: string quoting
    "RET",  # flake-return: return statement
    "RUF",  # Ruff-specific rules
    "S",  # flake8-bandit: security testing
    "SIM",  # flake-simplify: code simplifications
    "T20",  # flake8-print: print statements
    "TID",  # flake8-tidy-imports: absolute imports
    "UP",  # pyupgrade: upgrade syntax for newer versions of Python
    "W",  # pycodestyle: warnings
    "YTT",  # flake8-202: sys.version misuse
]
ignore = [
    "C408",  # unnecessary dict() call (conflicts with makeLogRecord())
    "COM812",  # trailing comma missing (conflicts with formatter)
    "B904",  # unchained exception raised within "except:" clause
    "E501",  # line too long
    "ISC001",  # implicit string concatenation on one line (conflicts with formatter)
    "N801",  # class name not title case
    "N818",  # exception class name doesn't end in "Error"
    "PLR0913",  # too many positional arguments in function definition
    "PLR0914",  # too many local variables
    "PLR0917",  # too many positional arguments
    "S105",  # hard-coded password
    "S404",  # subprocess import
    "SIM115",  # open() without context manager
    "SIM905",  # split() on literal string
]

[tool.ruff.lint.flake8-quotes]
docstring-quotes = "single"
inline-quotes = "single"
multiline-quotes = "single"

[tool.ruff.lint.isort]
known-first-party = ["borgmatic"]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
    "C406",  # unnecessary list literal
    "N802",  # uppercase in function name
    "PLC1901",  # comparison to empty string
    "PLR2004",  # magic value
    "PLW1514",  # open() without encoding
    "S101",  # asserts
    "S106",  # hard-coded password
    "S108",  # insecure usage of temporary file
    "S602",  # shell=True
    "S603",  # subprocess call
    "S604",  # shell=True
    "S607",  # executing a relative path
    "TID252",  # relative import from parent
]
"tests/end-to-end/commands/**/*.py" = [
    "T201",  # print statement
]

[tool.codespell]
skip = ".git,.tox,build"
