lintro 0.8.0__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lintro might be problematic. Click here for more details.

Files changed (201) hide show
  1. {lintro-0.8.0/lintro.egg-info → lintro-0.9.0}/PKG-INFO +1 -1
  2. {lintro-0.8.0 → lintro-0.9.0}/assets/images/coverage-badge.svg +1 -1
  3. {lintro-0.8.0 → lintro-0.9.0}/lintro/__init__.py +1 -1
  4. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/list_tools.py +1 -1
  5. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/actionlint_parser.py +1 -1
  6. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/tool_base.py +1 -1
  7. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_ruff.py +1 -1
  8. {lintro-0.8.0 → lintro-0.9.0/lintro.egg-info}/PKG-INFO +1 -1
  9. {lintro-0.8.0 → lintro-0.9.0}/pyproject.toml +2 -2
  10. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_hadolint_integration.py +14 -17
  11. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_ruff_integration.py +4 -4
  12. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_yamllint_integration.py +17 -21
  13. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_ci_post_pr_comment.py +1 -1
  14. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_ghcr_prune_untagged.py +2 -2
  15. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_script_environment.py +8 -8
  16. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_shell_scripts.py +7 -7
  17. {lintro-0.8.0 → lintro-0.9.0}/tests/test_documentation.py +9 -9
  18. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ascii_normalize.py +2 -2
  19. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils.py +3 -3
  20. {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_output_manager.py +2 -2
  21. {lintro-0.8.0 → lintro-0.9.0}/LICENSE +0 -0
  22. {lintro-0.8.0 → lintro-0.9.0}/MANIFEST.in +0 -0
  23. {lintro-0.8.0 → lintro-0.9.0}/README.md +0 -0
  24. {lintro-0.8.0 → lintro-0.9.0}/assets/images/lintro.png +0 -0
  25. {lintro-0.8.0 → lintro-0.9.0}/docs/README.md +0 -0
  26. {lintro-0.8.0 → lintro-0.9.0}/docs/configuration.md +0 -0
  27. {lintro-0.8.0 → lintro-0.9.0}/docs/contributing.md +0 -0
  28. {lintro-0.8.0 → lintro-0.9.0}/docs/coverage-setup.md +0 -0
  29. {lintro-0.8.0 → lintro-0.9.0}/docs/docker.md +0 -0
  30. {lintro-0.8.0 → lintro-0.9.0}/docs/getting-started.md +0 -0
  31. {lintro-0.8.0 → lintro-0.9.0}/docs/github-integration.md +0 -0
  32. {lintro-0.8.0 → lintro-0.9.0}/docs/lintro-self-use.md +0 -0
  33. {lintro-0.8.0 → lintro-0.9.0}/docs/security/assurance.md +0 -0
  34. {lintro-0.8.0 → lintro-0.9.0}/docs/security/requirements.md +0 -0
  35. {lintro-0.8.0 → lintro-0.9.0}/docs/style-guide.md +0 -0
  36. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/README.md +0 -0
  37. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/actionlint-analysis.md +0 -0
  38. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/bandit-analysis.md +0 -0
  39. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/black-analysis.md +0 -0
  40. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/darglint-analysis.md +0 -0
  41. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/hadolint-analysis.md +0 -0
  42. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/prettier-analysis.md +0 -0
  43. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/ruff-analysis.md +0 -0
  44. {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/yamllint-analysis.md +0 -0
  45. {lintro-0.8.0 → lintro-0.9.0}/lintro/__main__.py +0 -0
  46. {lintro-0.8.0 → lintro-0.9.0}/lintro/ascii-art/fail.txt +0 -0
  47. {lintro-0.8.0 → lintro-0.9.0}/lintro/ascii-art/success.txt +0 -0
  48. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli.py +0 -0
  49. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/__init__.py +0 -0
  50. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/__init__.py +0 -0
  51. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/check.py +0 -0
  52. {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/format.py +0 -0
  53. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/__init__.py +0 -0
  54. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/action.py +0 -0
  55. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/darglint_strictness.py +0 -0
  56. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/group_by.py +0 -0
  57. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/hadolint_enums.py +0 -0
  58. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/output_format.py +0 -0
  59. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/tool_name.py +0 -0
  60. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/tool_type.py +0 -0
  61. {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/yamllint_format.py +0 -0
  62. {lintro-0.8.0 → lintro-0.9.0}/lintro/exceptions/__init__.py +0 -0
  63. {lintro-0.8.0 → lintro-0.9.0}/lintro/exceptions/errors.py +0 -0
  64. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/__init__.py +0 -0
  65. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/__init__.py +0 -0
  66. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/output_style.py +0 -0
  67. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/table_descriptor.py +0 -0
  68. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/__init__.py +0 -0
  69. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/csv.py +0 -0
  70. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/grid.py +0 -0
  71. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/html.py +0 -0
  72. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/json.py +0 -0
  73. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/markdown.py +0 -0
  74. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/plain.py +0 -0
  75. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/__init__.py +0 -0
  76. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/actionlint_formatter.py +0 -0
  77. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/bandit_formatter.py +0 -0
  78. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/black_formatter.py +0 -0
  79. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/darglint_formatter.py +0 -0
  80. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/hadolint_formatter.py +0 -0
  81. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/prettier_formatter.py +0 -0
  82. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/ruff_formatter.py +0 -0
  83. {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/yamllint_formatter.py +0 -0
  84. {lintro-0.8.0 → lintro-0.9.0}/lintro/models/__init__.py +0 -0
  85. {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/__init__.py +0 -0
  86. {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool.py +0 -0
  87. {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool_config.py +0 -0
  88. {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool_result.py +0 -0
  89. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/__init__.py +0 -0
  90. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/__init__.py +0 -0
  91. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/actionlint_issue.py +0 -0
  92. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/black/black_issue.py +0 -0
  93. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/black/black_parser.py +0 -0
  94. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/__init__.py +0 -0
  95. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/darglint_issue.py +0 -0
  96. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/darglint_parser.py +0 -0
  97. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/__init__.py +0 -0
  98. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/hadolint_issue.py +0 -0
  99. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/hadolint_parser.py +0 -0
  100. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/__init__.py +0 -0
  101. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/prettier_issue.py +0 -0
  102. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/prettier_parser.py +0 -0
  103. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/__init__.py +0 -0
  104. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/ruff_issue.py +0 -0
  105. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/ruff_parser.py +0 -0
  106. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/__init__.py +0 -0
  107. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/yamllint_issue.py +0 -0
  108. {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/yamllint_parser.py +0 -0
  109. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/__init__.py +0 -0
  110. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/__init__.py +0 -0
  111. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/tool_manager.py +0 -0
  112. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/__init__.py +0 -0
  113. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_actionlint.py +0 -0
  114. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_bandit.py +0 -0
  115. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_black.py +0 -0
  116. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_darglint.py +0 -0
  117. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_hadolint.py +0 -0
  118. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_prettier.py +0 -0
  119. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_yamllint.py +0 -0
  120. {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/tool_enum.py +0 -0
  121. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/__init__.py +0 -0
  122. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/ascii_normalize_cli.py +0 -0
  123. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/config.py +0 -0
  124. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/console_logger.py +0 -0
  125. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/formatting.py +0 -0
  126. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/output_manager.py +0 -0
  127. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/path_utils.py +0 -0
  128. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/tool_executor.py +0 -0
  129. {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/tool_utils.py +0 -0
  130. {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/SOURCES.txt +0 -0
  131. {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/dependency_links.txt +0 -0
  132. {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/entry_points.txt +0 -0
  133. {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/requires.txt +0 -0
  134. {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/top_level.txt +0 -0
  135. {lintro-0.8.0 → lintro-0.9.0}/setup.cfg +0 -0
  136. {lintro-0.8.0 → lintro-0.9.0}/test_samples/Dockerfile.violations +0 -0
  137. {lintro-0.8.0 → lintro-0.9.0}/test_samples/actionlint_violations.yml +0 -0
  138. {lintro-0.8.0 → lintro-0.9.0}/test_samples/bandit_violations.py +0 -0
  139. {lintro-0.8.0 → lintro-0.9.0}/test_samples/darglint_violations.py +0 -0
  140. {lintro-0.8.0 → lintro-0.9.0}/test_samples/prettier_violations.js +0 -0
  141. {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_black_e501_wrappable.py +0 -0
  142. {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_clean.py +0 -0
  143. {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_violations.py +0 -0
  144. {lintro-0.8.0 → lintro-0.9.0}/test_samples/yaml_violations.yml +0 -0
  145. {lintro-0.8.0 → lintro-0.9.0}/tests/__init__.py +0 -0
  146. {lintro-0.8.0 → lintro-0.9.0}/tests/cli/__init__.py +0 -0
  147. {lintro-0.8.0 → lintro-0.9.0}/tests/cli/conftest.py +0 -0
  148. {lintro-0.8.0 → lintro-0.9.0}/tests/cli/test_cli.py +0 -0
  149. {lintro-0.8.0 → lintro-0.9.0}/tests/conftest.py +0 -0
  150. {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/__init__.py +0 -0
  151. {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/conftest.py +0 -0
  152. {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/test_formatters.py +0 -0
  153. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/__init__.py +0 -0
  154. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/conftest.py +0 -0
  155. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_actionlint_integration.py +0 -0
  156. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_bandit_integration.py +0 -0
  157. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_darglint_integration.py +0 -0
  158. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_prettier_integration.py +0 -0
  159. {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_ruff_black_policy.py +0 -0
  160. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/__init__.py +0 -0
  161. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_delete_previous_lintro_comments.py +0 -0
  162. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_extract_version.py +0 -0
  163. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_github_comment_utilities.py +0 -0
  164. {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_semantic_release_compute_next.py +0 -0
  165. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/__init__.py +0 -0
  166. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_command_building.py +0 -0
  167. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_config_hydration.py +0 -0
  168. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_formatter_mapping.py +0 -0
  169. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_parsing.py +0 -0
  170. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_formatter.py +0 -0
  171. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_parser.py +0 -0
  172. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_tool.py +0 -0
  173. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_tool_more.py +0 -0
  174. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_commands.py +0 -0
  175. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_commands_more.py +0 -0
  176. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_programmatic.py +0 -0
  177. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_compatibility_ruff_black.py +0 -0
  178. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_config_loader.py +0 -0
  179. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_config_loader_more.py +0 -0
  180. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_console_logger.py +0 -0
  181. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_console_logger_more.py +0 -0
  182. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_enums_and_normalizers.py +0 -0
  183. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_exceptions.py +0 -0
  184. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_formatters_tables.py +0 -0
  185. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_output_manager_reports.py +0 -0
  186. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_parsers_actionlint.py +0 -0
  187. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ruff_parser_additional.py +0 -0
  188. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ruff_parser_more.py +0 -0
  189. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_subprocess_validator.py +0 -0
  190. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_base_subprocess.py +0 -0
  191. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor.py +0 -0
  192. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_fmt_exclusion.py +0 -0
  193. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_more.py +0 -0
  194. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_post_checks.py +0 -0
  195. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_manager.py +0 -0
  196. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils_fallbacks.py +0 -0
  197. {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils_more.py +0 -0
  198. {lintro-0.8.0 → lintro-0.9.0}/tests/utils/__init__.py +0 -0
  199. {lintro-0.8.0 → lintro-0.9.0}/tests/utils/conftest.py +0 -0
  200. {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_formatting.py +0 -0
  201. {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_path_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lintro
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: A unified CLI tool for code formatting, linting, and quality assurance
5
5
  Author-email: TurboCoder13 <turbocoder13@gmail.com>
6
6
  License: MIT License
@@ -9,7 +9,7 @@
9
9
  </clipPath>
10
10
  <g clip-path="url(#a)">
11
11
  <path fill="#555" d="M0 0h63v20H0z"/>
12
- <path fill="#4c1" d="M63 0h36v20H63z"/>
12
+ <path fill="#e05d44" d="M63 0h36v20H63z"/>
13
13
  <path fill="url(#b)" d="M0 0h99v20H0z"/>
14
14
  </g>
15
15
  <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
@@ -1,3 +1,3 @@
1
1
  """Lintro - A unified CLI core for code formatting, linting, and quality assurance."""
2
2
 
3
- __version__ = "0.8.0"
3
+ __version__ = "0.9.0"
@@ -109,6 +109,6 @@ def list_tools(
109
109
  f.write(output_text + "\n")
110
110
  success_msg = f"Output written to: {output}"
111
111
  click.echo(success_msg)
112
- except IOError as e:
112
+ except OSError as e:
113
113
  error_msg = f"Error writing to file {output}: {e}"
114
114
  click.echo(error_msg, err=True)
@@ -8,7 +8,7 @@ uniform tables and reports across styles.
8
8
  from __future__ import annotations
9
9
 
10
10
  import re
11
- from typing import Iterable
11
+ from collections.abc import Iterable
12
12
 
13
13
  from lintro.parsers.actionlint.actionlint_issue import ActionlintIssue
14
14
 
@@ -102,7 +102,7 @@ class BaseTool(ABC):
102
102
  try:
103
103
  lintro_ignore_path = os.path.abspath(".lintro-ignore")
104
104
  if os.path.exists(lintro_ignore_path):
105
- with open(lintro_ignore_path, "r", encoding="utf-8") as f:
105
+ with open(lintro_ignore_path, encoding="utf-8") as f:
106
106
  for line in f:
107
107
  line_stripped = line.strip()
108
108
  if not line_stripped or line_stripped.startswith("#"):
@@ -59,7 +59,7 @@ def _load_lintro_ignore() -> list[str]:
59
59
 
60
60
  if lintro_ignore_path.exists():
61
61
  try:
62
- with open(lintro_ignore_path, "r", encoding="utf-8") as f:
62
+ with open(lintro_ignore_path, encoding="utf-8") as f:
63
63
  for line in f:
64
64
  line = line.strip()
65
65
  # Skip empty lines and comments
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lintro
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: A unified CLI tool for code formatting, linting, and quality assurance
5
5
  Author-email: TurboCoder13 <turbocoder13@gmail.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lintro"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  description = "A unified CLI tool for code formatting, linting, and quality assurance"
9
9
  keywords = [ "linting", "formatting", "code-quality", "cli", "python", "javascript", "yaml", "docker",]
10
10
  classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities",]
@@ -65,7 +65,7 @@ indent-style = "space"
65
65
  skip-magic-trailing-comma = false
66
66
 
67
67
  [tool.ruff.lint]
68
- select = [ "E", "F", "W", "I", "COM", "D",]
68
+ select = [ "E", "F", "W", "I", "COM", "D", "UP",]
69
69
  ignore = []
70
70
 
71
71
  [tool.ruff.pydocstyle]
@@ -39,15 +39,15 @@ def run_hadolint_directly(file_path: Path) -> tuple[bool, str, int]:
39
39
  print(f"[DEBUG] hadolint version: {version_result.stdout}")
40
40
  cmd = ["hadolint", "--no-color", "-f", "tty", str(file_path)]
41
41
  print(f"[DEBUG] Running hadolint command: {' '.join(cmd)}")
42
- with open(file_path, "r") as f:
42
+ with open(file_path) as f:
43
43
  print(f"[DEBUG] File contents for {file_path}:")
44
44
  print(f.read())
45
45
  with tempfile.TemporaryDirectory() as temp_home:
46
46
  env = os.environ.copy()
47
47
  env["HOME"] = temp_home
48
48
  print(
49
- "[DEBUG] Subprocess environment: HOME=%s, PATH=%s"
50
- % (env.get("HOME"), env.get("PATH")),
49
+ f"[DEBUG] Subprocess environment: HOME={env.get('HOME')}, "
50
+ f"PATH={env.get('PATH')}",
51
51
  )
52
52
  print(f"[DEBUG] Subprocess CWD: {file_path.parent}")
53
53
  print(f"[DEBUG] Subprocess full env: {env}")
@@ -61,7 +61,7 @@ def run_hadolint_directly(file_path: Path) -> tuple[bool, str, int]:
61
61
  )
62
62
  issues = []
63
63
  for line in result.stdout.splitlines():
64
- if any((level in line for level in ["error:", "warning:", "info:", "style:"])):
64
+ if any(level in line for level in ["error:", "warning:", "info:", "style:"]):
65
65
  issues.append(line)
66
66
  issues_count = len(issues)
67
67
  success = issues_count == 0 and result.returncode == 0
@@ -101,8 +101,8 @@ def test_hadolint_reports_violations_direct(tmp_path):
101
101
  print(f"[DEBUG] CWD: {os.getcwd()}")
102
102
  print(f"[DEBUG] Temp dir contents: {os.listdir(tmp_path)}")
103
103
  print(
104
- "[DEBUG] Environment: HOME=%s, PATH=%s"
105
- % (os.environ.get("HOME"), os.environ.get("PATH")),
104
+ f"[DEBUG] Environment: HOME={os.environ.get('HOME')}, "
105
+ f"PATH={os.environ.get('PATH')}",
106
106
  )
107
107
  logger.info("[TEST] Running hadolint directly on sample file...")
108
108
  success, output, issues = run_hadolint_directly(sample_file)
@@ -130,8 +130,8 @@ def test_hadolint_reports_violations_through_lintro(tmp_path):
130
130
  tool.set_options(no_color=True, format="tty")
131
131
  result = tool.check([str(sample_file)])
132
132
  logger.info(
133
- "[LOG] Lintro HadolintTool found %s issues. Output:\n%s"
134
- % (result.issues_count, result.output),
133
+ f"[LOG] Lintro HadolintTool found {result.issues_count} issues. "
134
+ f"Output:\n{result.output}",
135
135
  )
136
136
  assert (
137
137
  not result.success
@@ -159,8 +159,8 @@ def test_hadolint_output_consistency_direct_vs_lintro(tmp_path):
159
159
  print(f"[DEBUG] CWD: {os.getcwd()}")
160
160
  print(f"[DEBUG] Temp dir contents: {os.listdir(tmp_path)}")
161
161
  print(
162
- "[DEBUG] Environment: HOME=%s, PATH=%s"
163
- % (os.environ.get("HOME"), os.environ.get("PATH")),
162
+ f"[DEBUG] Environment: HOME={os.environ.get('HOME')}, "
163
+ f"PATH={os.environ.get('PATH')}",
164
164
  )
165
165
  logger.info("[TEST] Comparing hadolint CLI and Lintro HadolintTool outputs...")
166
166
  tool = HadolintTool()
@@ -170,13 +170,10 @@ def test_hadolint_output_consistency_direct_vs_lintro(tmp_path):
170
170
  logger.info(
171
171
  f"[LOG] CLI issues: {direct_issues}, Lintro issues: {result.issues_count}",
172
172
  )
173
- assert (
174
- direct_issues == result.issues_count
175
- ), "Mismatch: CLI=%s, Lintro=%s\nCLI Output:\n%s\nLintro Output:\n%s" % (
176
- direct_issues,
177
- result.issues_count,
178
- direct_output,
179
- result.output,
173
+ assert direct_issues == result.issues_count, (
174
+ f"Mismatch: CLI={direct_issues}, Lintro={result.issues_count}\n"
175
+ f"CLI Output:\n{direct_output}\n"
176
+ f"Lintro Output:\n{result.output}"
180
177
  )
181
178
  assert (
182
179
  direct_success == result.success
@@ -91,7 +91,7 @@ def temp_python_file(request):
91
91
  f.flush()
92
92
  file_path = f.name
93
93
  print(f"[DEBUG] temp_python_file path: {file_path}")
94
- with open(file_path, "r") as debug_f:
94
+ with open(file_path) as debug_f:
95
95
  print("[DEBUG] temp_python_file contents:")
96
96
  print(debug_f.read())
97
97
 
@@ -408,7 +408,7 @@ class TestRuffTool:
408
408
  line
409
409
  for line in result.stdout.splitlines()
410
410
  if ":" in line
411
- and any((code in line for code in ["E", "F", "I", "W"]))
411
+ and any(code in line for code in ["E", "F", "I", "W"])
412
412
  ],
413
413
  )
414
414
  lintro_result = tool.check([ruff_violation_file])
@@ -424,8 +424,8 @@ class TestRuffTool:
424
424
  else 0
425
425
  )
426
426
  logger.info(
427
- "[LOG] CLI issues: %s, Lintro lint issues: %s"
428
- % (direct_issues, lintro_lint_issues),
427
+ f"[LOG] CLI issues: {direct_issues}, "
428
+ f"Lintro lint issues: {lintro_lint_issues}",
429
429
  )
430
430
  assert direct_issues == lintro_lint_issues, (
431
431
  "Issue count mismatch: "
@@ -39,15 +39,15 @@ def run_yamllint_directly(file_path: Path) -> tuple[bool, str, int]:
39
39
  print(f"[DEBUG] yamllint version: {version_result.stdout}")
40
40
  cmd = ["yamllint", "-f", "parsable", file_path.name]
41
41
  print(f"[DEBUG] Running yamllint command: {' '.join(cmd)}")
42
- with open(file_path, "r") as f:
42
+ with open(file_path) as f:
43
43
  print(f"[DEBUG] File contents for {file_path}:")
44
44
  print(f.read())
45
45
  with tempfile.TemporaryDirectory() as temp_home:
46
46
  env = os.environ.copy()
47
47
  env["HOME"] = temp_home
48
48
  print(
49
- "[DEBUG] Subprocess environment: HOME=%s, PATH=%s"
50
- % (env.get("HOME"), env.get("PATH")),
49
+ f"[DEBUG] Subprocess environment: HOME={env.get('HOME')}, "
50
+ f"PATH={env.get('PATH')}",
51
51
  )
52
52
  print(f"[DEBUG] Subprocess CWD: {file_path.parent}")
53
53
  print(f"[DEBUG] Subprocess full env: {env}")
@@ -61,7 +61,7 @@ def run_yamllint_directly(file_path: Path) -> tuple[bool, str, int]:
61
61
  )
62
62
  issues = []
63
63
  for line in result.stdout.splitlines():
64
- if any((level in line for level in ["[error]", "[warning]"])):
64
+ if any(level in line for level in ["[error]", "[warning]"]):
65
65
  issues.append(line)
66
66
  issues_count = len(issues)
67
67
  success = issues_count == 0 and result.returncode == 0
@@ -102,8 +102,8 @@ def test_yamllint_reports_violations_direct(tmp_path):
102
102
  print(f"[DEBUG] CWD: {os.getcwd()}")
103
103
  print(f"[DEBUG] Temp dir contents: {os.listdir(tmp_path)}")
104
104
  print(
105
- "[DEBUG] Environment: HOME=%s, PATH=%s"
106
- % (os.environ.get("HOME"), os.environ.get("PATH")),
105
+ f"[DEBUG] Environment: HOME={os.environ.get('HOME')}, "
106
+ f"PATH={os.environ.get('PATH')}",
107
107
  )
108
108
  logger.info("[TEST] Running yamllint directly on sample file...")
109
109
  success, output, issues = run_yamllint_directly(sample_file)
@@ -131,8 +131,8 @@ def test_yamllint_reports_violations_through_lintro(tmp_path):
131
131
  tool.set_options(format="parsable")
132
132
  result = tool.check([str(sample_file)])
133
133
  logger.info(
134
- "[LOG] Lintro YamllintTool found %s issues. Output:\n%s"
135
- % (result.issues_count, result.output),
134
+ f"[LOG] Lintro YamllintTool found {result.issues_count} issues. "
135
+ f"Output:\n{result.output}",
136
136
  )
137
137
  assert (
138
138
  not result.success
@@ -164,12 +164,12 @@ def test_yamllint_output_consistency_direct_vs_lintro(tmp_path):
164
164
  print(f"[DEBUG] CWD: {os.getcwd()}")
165
165
  print(f"[DEBUG] Temp dir contents: {os.listdir(tmp_path)}")
166
166
  print(
167
- "[DEBUG] Environment: HOME=%s, PATH=%s"
168
- % (os.environ.get("HOME"), os.environ.get("PATH")),
167
+ f"[DEBUG] Environment: HOME={os.environ.get('HOME')}, "
168
+ f"PATH={os.environ.get('PATH')}",
169
169
  )
170
170
  print(
171
- "[DEBUG] Environment: HOME=%s, PATH=%s"
172
- % (os.environ.get("HOME"), os.environ.get("PATH")),
171
+ f"[DEBUG] Environment: HOME={os.environ.get('HOME')}, "
172
+ f"PATH={os.environ.get('PATH')}",
173
173
  )
174
174
  logger.info("[TEST] Comparing yamllint CLI and Lintro YamllintTool outputs...")
175
175
  tool = YamllintTool()
@@ -177,16 +177,12 @@ def test_yamllint_output_consistency_direct_vs_lintro(tmp_path):
177
177
  direct_success, direct_output, direct_issues = run_yamllint_directly(sample_file)
178
178
  result = tool.check([str(sample_file)])
179
179
  logger.info(
180
- "[LOG] CLI issues: %s, Lintro issues: %s"
181
- % (direct_issues, result.issues_count),
180
+ f"[LOG] CLI issues: {direct_issues}, Lintro issues: {result.issues_count}",
182
181
  )
183
- assert (
184
- direct_issues == result.issues_count
185
- ), "Mismatch: CLI=%s, Lintro=%s\nCLI Output:\n%s\nLintro Output:\n%s" % (
186
- direct_issues,
187
- result.issues_count,
188
- direct_output,
189
- result.output,
182
+ assert direct_issues == result.issues_count, (
183
+ f"Mismatch: CLI={direct_issues}, Lintro={result.issues_count}\n"
184
+ f"CLI Output:\n{direct_output}\n"
185
+ f"Lintro Output:\n{result.output}"
190
186
  )
191
187
 
192
188
 
@@ -278,7 +278,7 @@ def test_script_has_proper_shebang(ci_script_path: Path) -> None:
278
278
  Args:
279
279
  ci_script_path (Path): Path to the script being tested.
280
280
  """
281
- with open(ci_script_path, "r") as f:
281
+ with open(ci_script_path) as f:
282
282
  first_line = f.readline().strip()
283
283
 
284
284
  assert_that(first_line).starts_with("#!/bin/bash")
@@ -160,7 +160,7 @@ def test_main_deletes_only_untagged(monkeypatch):
160
160
  ) -> None: # noqa: ARG002
161
161
  pass
162
162
 
163
- def __enter__(self) -> "DummyClient": # type: ignore[name-defined]
163
+ def __enter__(self) -> DummyClient: # type: ignore[name-defined]
164
164
  return self
165
165
 
166
166
  def __exit__(self, exc_type, exc, tb) -> None: # noqa: ANN001
@@ -245,7 +245,7 @@ def test_main_respects_keep_n_and_dry_run(monkeypatch):
245
245
  ) -> None: # noqa: ARG002
246
246
  pass
247
247
 
248
- def __enter__(self) -> "DummyClient": # type: ignore[name-defined]
248
+ def __enter__(self) -> DummyClient: # type: ignore[name-defined]
249
249
  return self
250
250
 
251
251
  def __exit__(self, exc_type, exc, tb) -> None: # noqa: ANN001
@@ -469,7 +469,7 @@ class TestScriptSecurity:
469
469
  shell_scripts = list(scripts_dir.glob("*.sh"))
470
470
  dangerous_patterns = ["eval ", "exec ", "$(curl", "| sh", "| bash"]
471
471
  for script in shell_scripts:
472
- with open(script, "r") as f:
472
+ with open(script) as f:
473
473
  content = f.read()
474
474
  for pattern in dangerous_patterns:
475
475
  if pattern in content:
@@ -505,7 +505,7 @@ class TestScriptSecurity:
505
505
  script = scripts_dir / script_name
506
506
  if not script.exists():
507
507
  continue
508
- with open(script, "r") as f:
508
+ with open(script) as f:
509
509
  content = f.read()
510
510
  has_validation = any(
511
511
  (
@@ -532,14 +532,14 @@ class TestScriptSecurity:
532
532
  """
533
533
  shell_scripts = list(scripts_dir.glob("*.sh"))
534
534
  for script in shell_scripts:
535
- with open(script, "r") as f:
535
+ with open(script) as f:
536
536
  content = f.read()
537
537
  lines = content.split("\n")
538
538
  for i, line in enumerate(lines, 1):
539
539
  if line.strip().startswith("#"):
540
540
  continue
541
541
  if " $1" in line and '"$1"' not in line and ("'$1'" not in line):
542
- if not any((safe in line for safe in ["[$1]", "=$1", "shift"])):
542
+ if not any(safe in line for safe in ["[$1]", "=$1", "shift"]):
543
543
  pass
544
544
 
545
545
 
@@ -563,7 +563,7 @@ class TestScriptCompatibility:
563
563
  """
564
564
  shell_scripts = list(scripts_dir.glob("*.sh"))
565
565
  for script in shell_scripts:
566
- with open(script, "r") as f:
566
+ with open(script) as f:
567
567
  first_line = f.readline().strip()
568
568
  assert (
569
569
  first_line == "#!/bin/bash"
@@ -577,10 +577,10 @@ class TestScriptCompatibility:
577
577
  """
578
578
  shell_scripts = list(scripts_dir.glob("*.sh"))
579
579
  for script in shell_scripts:
580
- with open(script, "r") as f:
580
+ with open(script) as f:
581
581
  first_line = f.readline().strip()
582
582
  if first_line == "#!/bin/sh":
583
- with open(script, "r") as f:
583
+ with open(script) as f:
584
584
  content = f.read()
585
585
  bash_features = ["[[", "function ", "$(", "source "]
586
586
  for feature in bash_features:
@@ -599,7 +599,7 @@ class TestScriptCompatibility:
599
599
  f for f in scripts_dir.glob("*.py") if f.name != "__init__.py"
600
600
  ]
601
601
  for script in python_scripts:
602
- with open(script, "r") as f:
602
+ with open(script) as f:
603
603
  first_line = f.readline().strip()
604
604
  assert first_line in [
605
605
  "#!/usr/bin/env python3",
@@ -44,7 +44,7 @@ class TestShellScriptSyntax:
44
44
  shell_scripts: List of shell script file paths.
45
45
  """
46
46
  for script in shell_scripts:
47
- with open(script, "r") as f:
47
+ with open(script) as f:
48
48
  first_line = f.readline().strip()
49
49
  assert first_line.startswith("#!"), f"{script.name} missing shebang"
50
50
  assert "bash" in first_line, f"{script.name} should use bash"
@@ -89,7 +89,7 @@ class TestShellScriptSyntax:
89
89
  ]
90
90
  for script in shell_scripts:
91
91
  if script.name in critical_scripts:
92
- with open(script, "r") as f:
92
+ with open(script) as f:
93
93
  content = f.read()
94
94
  assert "set -e" in content, f"{script.name} should use 'set -e'"
95
95
 
@@ -147,7 +147,7 @@ class TestScriptHelp:
147
147
  scripts_dir: Path to the scripts directory.
148
148
  """
149
149
  script = scripts_dir / "utils" / "install-tools.sh"
150
- with open(script, "r") as f:
150
+ with open(script) as f:
151
151
  content = f.read()
152
152
  assert "Usage:" in content, "install-tools.sh should have usage documentation"
153
153
  assert (
@@ -274,7 +274,7 @@ class TestScriptFunctionality:
274
274
  for script_name in docker_scripts:
275
275
  script = scripts_dir / script_name
276
276
  if script.exists():
277
- with open(script, "r") as f:
277
+ with open(script) as f:
278
278
  content = f.read()
279
279
  assert any(
280
280
  (
@@ -378,7 +378,7 @@ class TestScriptIntegration:
378
378
  if p.name != "semantic-release-compute-next.sh"
379
379
  ]
380
380
  for script in ci_scripts:
381
- with open(script, "r") as f:
381
+ with open(script) as f:
382
382
  content = f.read()
383
383
  if "run-tests.sh" in content:
384
384
  assert_that((scripts_dir / "run-tests.sh").exists()).is_true()
@@ -433,7 +433,7 @@ class TestScriptIntegration:
433
433
  shell_scripts = list(scripts_dir.glob("*.sh"))
434
434
  color_patterns = []
435
435
  for script in shell_scripts:
436
- with open(script, "r") as f:
436
+ with open(script) as f:
437
437
  content = f.read()
438
438
  if "RED=" in content and "GREEN=" in content:
439
439
  for line in content.split("\n"):
@@ -458,7 +458,7 @@ class TestScriptIntegration:
458
458
  for script_name in critical_scripts:
459
459
  script = scripts_dir / script_name
460
460
  if script.exists():
461
- with open(script, "r") as f:
461
+ with open(script) as f:
462
462
  lines = [f.readline() for _ in range(20)]
463
463
  header = "".join(lines)
464
464
  assert any(
@@ -58,7 +58,7 @@ class TestScriptDocumentation:
58
58
  if not Path(doc_file).exists():
59
59
  continue
60
60
 
61
- with open(doc_file, "r", encoding="utf-8") as f:
61
+ with open(doc_file, encoding="utf-8") as f:
62
62
  content = f.read()
63
63
 
64
64
  # Find script references (patterns like ./scripts/...)
@@ -89,7 +89,7 @@ class TestScriptDocumentation:
89
89
  if not scripts_readme.exists():
90
90
  pytest.skip("scripts/README.md not found")
91
91
 
92
- with open(scripts_readme, "r", encoding="utf-8") as f:
92
+ with open(scripts_readme, encoding="utf-8") as f:
93
93
  content = f.read()
94
94
 
95
95
  # Get all script files
@@ -146,7 +146,7 @@ class TestCLIDocumentation:
146
146
  if not Path(doc_file).exists():
147
147
  continue
148
148
 
149
- with open(doc_file, "r", encoding="utf-8") as f:
149
+ with open(doc_file, encoding="utf-8") as f:
150
150
  content = f.read()
151
151
 
152
152
  # Find code blocks with lintro commands
@@ -209,7 +209,7 @@ class TestDocumentationLinks:
209
209
  if not Path(doc_file).exists():
210
210
  continue
211
211
 
212
- with open(doc_file, "r", encoding="utf-8") as f:
212
+ with open(doc_file, encoding="utf-8") as f:
213
213
  content = f.read()
214
214
 
215
215
  # Find markdown links
@@ -245,7 +245,7 @@ class TestDocumentationLinks:
245
245
  if not Path(doc_file).exists():
246
246
  continue
247
247
 
248
- with open(doc_file, "r", encoding="utf-8") as f:
248
+ with open(doc_file, encoding="utf-8") as f:
249
249
  content = f.read()
250
250
 
251
251
  # Find workflow references
@@ -278,7 +278,7 @@ class TestDocumentationCompleteness:
278
278
  if not Path(doc_file).exists():
279
279
  continue
280
280
 
281
- with open(doc_file, "r", encoding="utf-8") as f:
281
+ with open(doc_file, encoding="utf-8") as f:
282
282
  first_line = f.readline().strip()
283
283
 
284
284
  if not first_line.startswith("# "):
@@ -293,7 +293,7 @@ class TestDocumentationCompleteness:
293
293
  if not scripts_readme.exists():
294
294
  pytest.skip("scripts/README.md not found")
295
295
 
296
- with open(scripts_readme, "r", encoding="utf-8") as f:
296
+ with open(scripts_readme, encoding="utf-8") as f:
297
297
  content = f.read()
298
298
 
299
299
  # Check for directory structure section
@@ -323,7 +323,7 @@ class TestDocumentationConsistency:
323
323
  if not Path(doc_file).exists():
324
324
  continue
325
325
 
326
- with open(doc_file, "r", encoding="utf-8") as f:
326
+ with open(doc_file, encoding="utf-8") as f:
327
327
  content = f.read()
328
328
 
329
329
  # Check for old command aliases that shouldn't be in docs
@@ -353,7 +353,7 @@ class TestDocumentationConsistency:
353
353
  if not Path(doc_file).exists():
354
354
  continue
355
355
 
356
- with open(doc_file, "r", encoding="utf-8") as f:
356
+ with open(doc_file, encoding="utf-8") as f:
357
357
  content = f.read()
358
358
 
359
359
  # Check for old --table-format references
@@ -20,7 +20,7 @@ def test_normalize_ascii_block_center_and_alignments():
20
20
  valign="middle",
21
21
  )
22
22
  assert_that(len(out)).is_equal_to(5)
23
- assert_that(all((len(line) == 10 for line in out))).is_true()
23
+ assert_that(all(len(line) == 10 for line in out)).is_true()
24
24
  assert_that({"XX", "XXXX", "X"}).contains(out[2].strip())
25
25
  left = normalize_ascii_block(["X"], width=5, height=1, align="left")
26
26
  right = normalize_ascii_block(["X"], width=5, height=1, align="right")
@@ -40,4 +40,4 @@ def test_normalize_ascii_file_sections(tmp_path: Path):
40
40
  assert_that(len(sections)).is_equal_to(2)
41
41
  for sec in sections:
42
42
  assert_that(len(sec)).is_equal_to(3)
43
- assert_that(all((len(line) == 6 for line in sec))).is_true()
43
+ assert_that(all(len(line) == 6 for line in sec)).is_true()
@@ -75,9 +75,9 @@ def test_walk_files_with_excludes(tmp_path):
75
75
  exclude_patterns=["ignore*"],
76
76
  include_venv=False,
77
77
  )
78
- assert_that(any((p.endswith("a.py") for p in files))).is_true()
79
- assert_that(any((p.endswith("b.js") for p in files))).is_true()
80
- assert_that(any((p.endswith("ignore.txt") for p in files))).is_false()
78
+ assert_that(any(p.endswith("a.py") for p in files)).is_true()
79
+ assert_that(any(p.endswith("b.js") for p in files)).is_true()
80
+ assert_that(any(p.endswith("ignore.txt") for p in files)).is_false()
81
81
 
82
82
 
83
83
  def test_is_venv_directory_predicate():
@@ -162,5 +162,5 @@ def test_write_reports_from_results(temp_output_dir):
162
162
  with open(csv_path) as f:
163
163
  reader = list(csv.reader(f))
164
164
  assert_that(reader[0][:2]).is_equal_to(["tool", "issues_count"])
165
- assert_that(any(("tool1" in row for row in reader))).is_true()
166
- assert_that(any(("foo.py" in row for row in reader))).is_true()
165
+ assert_that(any("tool1" in row for row in reader)).is_true()
166
+ assert_that(any("foo.py" in row for row in reader)).is_true()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes