[tool.ruff] line-length = 88 target-version = 'py39' # Modules and module_utils run on the managed node, down to Python 3.6 on RHEL 8, and their # tests run there too (tox.ini, py36-target). py37 is the oldest target ruff knows; it keeps # the formatter and pyupgrade from introducing newer syntax such as parenthesized context # managers. per-file-target-version = { 'plugins/module_utils/**' = 'py37', 'plugins/modules/**' = 'py37', 'tests/ansible_harness.py' = 'py37', 'tests/conftest.py' = 'py37', 'tests/exoscale_fake.py' = 'py37', 'tests/unit/plugins/module_utils/**' = 'py37', 'tests/unit/plugins/modules/**' = 'py37' } # Vendored upstream code that is kept as-is so patches stay sendable, plus the # vulture whitelist, which is a list of bare names by construction and not # runnable Python. exclude = [ '.vulture_whitelist.py', 'plugins/module_utils/gnupg.py', 'plugins/modules/ipa*.py', ] [tool.ruff.lint] select = [ 'B', # flake8-bugbear (potential bugs) 'C4', # flake8-comprehensions 'E', # pycodestyle errors 'F', # pyflakes (logic errors) 'I', # isort (import sorting) 'RUF', # Ruff-specific rules 'SIM', # flake8-simplify 'UP', # pyupgrade (modernize syntax for py39+) 'W', # pycodestyle warnings ] ignore = [ 'C408', # dict() instead of a literal (Ansible argument_spec convention) 'E402', # import not at top of file (the DOCUMENTATION block comes first) 'E501', # line too long (handled by code review, not auto-enforcement) 'SIM102', # nested if statements (sometimes clearer than combined conditions) 'SIM105', # contextlib.suppress (try/except/pass is more explicit) 'UP001', # __metaclass__ = type is obsolete (Ansible module preamble) 'UP009', # UTF-8 encoding declaration (we keep our standard file header) 'UP010', # unnecessary __future__ import (Ansible module preamble) 'UP015', # redundant open() mode (we keep explicit modes for clarity) ] [tool.ruff.format] docstring-code-format = true quote-style = 'single' # Configuration for tools that the LFOps repo runs under pre-commit. # This file does *not* describe the Ansible collection itself — that lives # in galaxy.yml. It exists only to point the linters at the right paths. [tool.vulture] # The pre-commit hook passes the files explicitly (see .pre-commit-config.yaml), so # `paths` only applies to a plain `vulture` run by hand, which only finds `*.py` files # there and misses the extension-less scripts in `tools/`. # # The whitelist file lists pre-existing findings (tracked in # https://github.com/Linuxfabrik/lfops/issues/221) so unrelated commits # don't fail the hook. Drop entries from .vulture_whitelist.py as the # real issues are fixed. paths = ['plugins', '.vulture_whitelist.py'] min_confidence = 80 [tool.pytest.ini_options] # Unit tests for the in-house plugins. The matrix of Python / ansible-core # versions is driven by tox; see tox.ini. testpaths = ['tests/unit'] # importlib mode lets same-named test files live in different plugin-type # directories (e.g. modules/ and lookup/ both have test_bitwarden_item.py) # without needing __init__.py packages. addopts = ['--import-mode=importlib'] [tool.bandit] # B110 (try/except/pass) and B112 (try/except/continue): intentional patterns # for graceful degradation. # B311 (pseudo-random): not used for cryptographic purposes. skips = ['B110', 'B112', 'B311'] [tool.bandit.assert_used] # A test suite may assert with the bare statement, so B101 does not apply under # tests/. bandit still scans the directory for every other finding. skips = ['*/tests/*.py', 'tests/*.py']