[project] name = "testsandmisc" version = "0.1.0" description = "Collection of miscellaneous tests and scripts" requires-python = ">=3.10" # ============================================================================ # RUFF - Extremely fast Python linter and formatter (written in Rust) # ============================================================================ [tool.ruff] target-version = "py310" # Include all Python files include = ["*.py", "**/*.py"] # Exclude vendored/build directories exclude = [ ".git", ".venv", "__pycache__", "build", "dist", ".eggs", "Bash/ffmpeg-build", # Vendored FFmpeg tools ] [tool.ruff.lint] # AGGRESSIVE: Select ALL rules from all categories select = ["ALL"] # Ignores for rules that are too strict for this mixed script repository ignore = [ # D203 vs D211 conflict - we use D211 (no blank line before class docstring) "D203", # 1 blank line required before class docstring (conflicts with D211) # D212 vs D213 conflict - we use D212 (summary on first line after """) "D213", # Multi-line docstring summary should start at second line (conflicts with D212) # Formatter conflicts - recommended to disable when using ruff format # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules "COM812", # Trailing comma missing - formatter handles this automatically "ISC001", # Implicit string concatenation - formatter may create these when wrapping # Security audit - prone to false positives with validated input # https://github.com/astral-sh/ruff/issues/4045 "S603", # subprocess call without shell - prone to false positives as it is # difficult to determine whether the passed arguments have been validated ] # Allow ALL rules to be auto-fixed fixable = ["ALL"] unfixable = [] # Per-file ignores [tool.ruff.lint.per-file-ignores] # Test files - allow test-specific patterns (assert, magic values) "**/tests/**/*.py" = [ "S101", # Allow assert in tests "PLR2004", # Allow magic values in tests "SLF001", # Allow private member access in tests ] "**/test_*.py" = [ "S101", # Allow assert in tests "S310", # Allow URL open in tests "S607", # Allow partial executable path in tests "PLC0415", # Allow late imports for test isolation "PLR2004", # Allow magic values in tests "SLF001", # Allow private member access in tests ] "poker_modifier_app/poker_modifier_app.py" = [ "FBT003", # Boolean positional values in tkinter API calls ] "python_pkg/keyboard_coop/main.py" = [ "FBT003", # Boolean positional values in pygame API calls (e.g., font.render) ] "python_pkg/screen_locker/screen_lock.py" = [ "FBT003", # Boolean positional values in tkinter API calls ] # Music generator - CLI script with intentional patterns "python_pkg/music_gen/music_generator.py" = [ "T201", # print() is intentional for CLI feedback "PLC0415", # Late imports for dependency checking "C901", # Complex interactive mode is acceptable "PLR0912", # Too many branches in interactive mode ] # Cinema planner - CLI tool with print output "python_pkg/cinema_planner/*.py" = [ "ARG001", # Unused function argument (callbacks) "T201", # print() is intentional for CLI output "D101", # Missing docstring in public class "D102", # Missing docstring in public method "D103", # Missing docstring in public function "D104", # Missing docstring in public package "ANN201", # Missing return type annotation "ANN202", # Missing return type annotation (private) "C901", # Complex functions acceptable for CLI "E501", # Line too long "EM102", # Exception f-string literal "PERF203", # try-except in loop "PERF401", # List comprehension "PLR0912", # Too many branches "PLR0915", # Too many statements "PLR2004", # Magic values "PLR1714", # Multiple comparisons "PTH123", # open() instead of Path.open() "S607", # Partial executable path "SIM105", # Use contextlib.suppress "TRY003", # Long exception messages ] # Linux configuration scripts - standalone scripts "linux_configuration/**/*.py" = [ "ARG001", # Unused function argument (signal handlers) "BLE001", # Blind exception catching in scripts "T201", # print() is intentional for scripts "ANN001", # Missing function argument type annotation "ANN201", # Missing return type annotation "ANN202", # Missing return type annotation (private) "ANN204", # Missing return type for __init__ "C901", # Complex functions in scripts "D100", # Missing module docstring "D103", # Missing docstring in public function "D107", # Missing docstring in __init__ "D205", # 1 blank line required between summary and description "D415", # First line should end with period "DTZ005", # datetime without timezone "E501", # Line too long "EXE001", # Shebang without executable permission "N806", # Non-lowercase variable name "PERF203", # try-except in loop "PGH003", # Use specific rule codes "PLR0912", # Too many branches "PLR0915", # Too many statements "PLR2004", # Magic values "PTH100", # Path manipulation "PTH103", # Path manipulation "PTH108", # Path manipulation "PTH110", # Path manipulation "PTH111", # Path manipulation "PTH112", # Path manipulation "PTH118", # Path manipulation "PTH119", # Path manipulation "PTH120", # Path manipulation "PTH122", # Path manipulation "PTH123", # open() instead of Path.open() "PTH202", # Path manipulation "S110", # try-except-pass "S607", # Partial executable path "SIM102", # Collapsible if "SIM105", # Use contextlib.suppress "SIM115", # Use context manager "TRY300", # Consider else block ] # Word frequency package - legacy code with pre-existing complexity "python_pkg/word_frequency/*.py" = [ "C901", # Function complexity - legacy code "PLR0911", # Too many return statements - legacy code "PLR0912", # Too many branches - legacy code "PLR0913", # Too many arguments - legacy code "PLR0915", # Too many statements - legacy code "PLR2004", # Magic values - legacy code "FBT001", # Boolean typed argument - legacy code "FBT002", # Boolean default argument - legacy code "FBT003", # Boolean positional value - legacy code "T201", # print() used for CLI feedback "TRY003", # Long exception messages - legacy code "EM101", # Exception string literal - legacy code "EM102", # Exception f-string literal - legacy code "SIM105", # Use contextlib.suppress - legacy code "SIM108", # Use ternary operator - legacy code "SIM117", # Use single with statement - legacy code "PLW2901", # Loop variable overwritten - legacy code "PLW0603", # Global statement - legacy code "TRY300", # Consider else block - legacy code "TRY301", # Abstract raise - legacy code "PTH123", # open() instead of Path.open() - legacy code "EXE001", # Shebang without executable - legacy code "ARG001", # Unused function argument - legacy code "ARG002", # Unused method argument - legacy code "ARG005", # Unused lambda argument - legacy code "F401", # Unused import - legacy code "F841", # Unused variable - legacy code "TC003", # Move stdlib import to type-checking block - legacy code "SLF001", # Private member access - legacy code "SIM101", # Multiple isinstance calls - legacy code "PERF401", # List comprehension - legacy code "N806", # Non-lowercase variable - legacy code "C416", # Unnecessary list comprehension - legacy code "E501", # Line too long - legacy code ] # Thesis diagram generators - one-off matplotlib plotting scripts "python_pkg/praca_magisterska_video/**/*.py" = [ "ANN001", # Missing type annotation - plotting scripts, not library code "ANN202", # Missing return type (private) "BLE001", # Blind exception (file I/O error handling) "C901", # Function complexity - long plotting functions "E501", # Line too long - matplotlib call chains "E741", # Ambiguous variable name - math convention (l, I) "ERA001", # Commented-out code - contains notes and alternatives "FBT002", # Boolean default argument - matplotlib patterns "FBT003", # Boolean positional value - matplotlib API calls "N806", # Uppercase variable - math convention (X, Y, F_A) "PERF203", # try-except in loop - file processing "PERF401", # List append in loop "PLR0912", # Too many branches - plotting functions "PLR0913", # Too many arguments - plotting functions "PLR0915", # Too many statements - plotting functions "PLR2004", # Magic values - plot coordinates and sizes "PLW2901", # Loop variable overwritten - data processing "S110", # try-except-pass - optional dependency handling "T201", # print() for script output ] [tool.ruff.lint.pydocstyle] convention = "google" # Use Google docstring convention [tool.ruff.lint.isort] force-single-line = false force-sort-within-sections = true known-first-party = ["python_pkg"] [tool.ruff.lint.flake8-quotes] docstring-quotes = "double" inline-quotes = "double" [tool.ruff.lint.flake8-tidy-imports] ban-relative-imports = "all" [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" docstring-code-format = true # ============================================================================ # MYPY - Static type checker (most aggressive settings) # ============================================================================ [tool.mypy] python_version = "3.10" # Strict mode enables most checks strict = true # Additional aggressive settings 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 # Extra strict settings disallow_any_unimported = true disallow_any_explicit = false # Too aggressive for practical use disallow_any_generics = true disallow_subclassing_any = true strict_equality = true extra_checks = true # Allow missing imports for third-party packages ignore_missing_imports = true # Show error codes show_error_codes = true # Enable colored output color_output = true # Exclude vendored directories exclude = [ "Bash/ffmpeg-build/", ".venv/", "python_pkg/music_gen/", # Uses dynamic imports from transformers "python_pkg/praca_magisterska_video/", # Thesis plotting scripts ] # ============================================================================ # PYLINT - Comprehensive Python linter # ============================================================================ [tool.pylint.main] # Analyse import fallback blocks analyse-fallback-blocks = true # Pickle collected data for later comparisons persistent = true # Jobs to use for parallel execution (0 = auto) jobs = 0 # Minimum Python version py-version = "3.10" # Ignore vendored directories ignore = ["Bash", ".venv", "__pycache__"] # Ignore patterns ignore-patterns = [".*\\.pyi$"] # Allow C extension modules to be introspected extension-pkg-allow-list = ["cv2", "pygame", "lxml"] [tool.pylint.messages_control] # Enable all checks by disabling disable enable = "all" # No disabled checks - maximum strictness disable = [] [tool.pylint.design] # A class with just run() as public API is valid for games/apps min-public-methods = 1 [tool.pylint.spelling] # No spelling dictionary to avoid false positives spelling-dict = "" [tool.pylint.typecheck] # cv2 (OpenCV) dynamically loads members from C extension at runtime generated-members = ["cv2.*"] # ============================================================================ # BANDIT - Security linter # ============================================================================ [tool.bandit] # Exclude test directories and vendored code exclude_dirs = ["tests", ".venv", "Bash/ffmpeg-build", "python_pkg/lichess_bot/.venv"] # ============================================================================ # BLACK & ISORT - Removed (ruff handles formatting and import sorting) # ============================================================================ # ============================================================================ # PYTEST - Testing framework configuration # ============================================================================ [tool.pytest.ini_options] testpaths = ["tests", "python_pkg", "articles"] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "-v", "--strict-markers", "--strict-config", "-ra", ] filterwarnings = [ "error", "ignore::DeprecationWarning", ] # ============================================================================ # COVERAGE - Code coverage configuration # ============================================================================ [tool.coverage.run] source = ["."] branch = true omit = [ "*/__pycache__/*", "*/tests/*", "*/.venv/*", "Bash/*", ] [tool.coverage.report] # Fail under this percentage fail_under = 100 show_missing = true skip_covered = false exclude_lines = [ # Standard exclusions "pragma: no cover", # Unreachable defensive code "raise NotImplementedError", "raise AssertionError", # Type checking imports "if TYPE_CHECKING:", # Main script entry point 'if __name__ == "__main__":', ] # Partial branch exclusions for unreachable branches partial_branches = [ "pragma: no branch", ] # ============================================================================ # VULTURE - Dead code detection # ============================================================================ # Note: Vulture uses command-line args, but we can document settings here # vulture --min-confidence 80 --exclude ".venv,Bash" . # ============================================================================ # FLAKE8 - Python linter (via Flake8-pyproject for pyproject.toml support) # ============================================================================ [tool.flake8] # Maximum line length (matches ruff/black) max-line-length = 88 # Maximum McCabe complexity (matches ruff C901 threshold) max-complexity = 10 # Maximum cognitive complexity (flake8-cognitive-complexity) max-cognitive-complexity = 12 # Maximum function length (flake8-functions) max-function-length = 20 # Maximum returns/arguments per function max-returns-amount = 6 max-arguments = 5 # Docstring convention (matches ruff) docstring-convention = "google" # Select all error codes select = ["E", "F", "W", "C", "B", "B950"] # Extend with plugin codes extend-select = ["B", "B9", "C4", "SIM", "PT", "TC", "ANN"] # Ignore rules that conflict with ruff-format or are duplicated extend-ignore = [ "E501", # Line too long - B950 from bugbear is smarter (allows 10% overflow) "W503", # Line break before binary operator - contradicts PEP 8 update "ANN101", # Missing type annotation for self "ANN102", # Missing type annotation for cls ] # Exclude directories exclude = [ ".git", ".venv", "__pycache__", "build", "dist", ".eggs", "Bash/ffmpeg-build", ] # Per-file ignores per-file-ignores = [ "**/tests/**/*.py:S101,ANN", "**/test_*.py:S101,ANN", ] # ============================================================================ # PYDOCSTYLE - Docstring style checker (ruff handles this, but for standalone) # ============================================================================ # Configured in ruff.lint.pydocstyle above