lintro 0.10.0__tar.gz → 0.11.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.
- {lintro-0.10.0/lintro.egg-info → lintro-0.11.0}/PKG-INFO +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/ruff-analysis.md +1 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/__init__.py +1 -1
- {lintro-0.10.0 → lintro-0.11.0/lintro.egg-info}/PKG-INFO +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/lintro.egg-info/SOURCES.txt +2 -0
- {lintro-0.10.0 → lintro-0.11.0}/pyproject.toml +3 -3
- lintro-0.11.0/test_samples/ruff_annotations_violations.py +53 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/cli/test_cli.py +8 -8
- {lintro-0.10.0 → lintro-0.11.0}/tests/conftest.py +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/tests/formatters/test_formatters.py +16 -16
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/conftest.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_actionlint_integration.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_darglint_integration.py +4 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_hadolint_integration.py +8 -8
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_prettier_integration.py +5 -5
- lintro-0.11.0/tests/integration/test_ruff_annotations.py +78 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_ruff_integration.py +25 -22
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_yamllint_integration.py +9 -9
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_delete_previous_lintro_comments.py +5 -5
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_ghcr_prune_untagged.py +7 -7
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_script_environment.py +29 -17
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_shell_scripts.py +24 -24
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_ascii_normalize.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_bandit_parsing.py +7 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_black_formatter.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_black_parser.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_black_tool.py +8 -5
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_black_tool_more.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_cli_commands.py +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_cli_commands_more.py +5 -5
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_cli_programmatic.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_compatibility_ruff_black.py +9 -9
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_config_loader.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_config_loader_more.py +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_console_logger.py +7 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_console_logger_more.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_enums_and_normalizers.py +6 -6
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_exceptions.py +1 -1
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_formatters_tables.py +4 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_output_manager_reports.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_parsers_actionlint.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_ruff_parser_additional.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_ruff_parser_more.py +4 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_subprocess_validator.py +4 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_base_subprocess.py +5 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_executor.py +29 -28
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_executor_more.py +22 -16
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_executor_post_checks.py +15 -11
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_manager.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_utils.py +5 -5
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_utils_fallbacks.py +2 -2
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_utils_more.py +12 -4
- {lintro-0.10.0 → lintro-0.11.0}/tests/utils/test_formatting.py +3 -3
- {lintro-0.10.0 → lintro-0.11.0}/tests/utils/test_output_manager.py +7 -7
- {lintro-0.10.0 → lintro-0.11.0}/tests/utils/test_path_utils.py +7 -7
- {lintro-0.10.0 → lintro-0.11.0}/LICENSE +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/MANIFEST.in +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/README.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/assets/images/coverage-badge.svg +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/assets/images/lintro.png +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/README.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/configuration.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/contributing.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/coverage-setup.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/docker.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/getting-started.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/github-integration.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/lintro-self-use.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/security/assurance.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/security/requirements.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/style-guide.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/README.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/actionlint-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/bandit-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/black-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/darglint-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/hadolint-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/prettier-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/docs/tool-analysis/yamllint-analysis.md +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/__main__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/ascii-art/fail.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/ascii-art/success.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli_utils/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli_utils/commands/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli_utils/commands/check.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli_utils/commands/format.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/cli_utils/commands/list_tools.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/action.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/darglint_strictness.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/group_by.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/hadolint_enums.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/output_format.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/tool_name.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/tool_type.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/enums/yamllint_format.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/exceptions/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/exceptions/errors.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/core/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/core/output_style.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/core/table_descriptor.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/csv.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/grid.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/html.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/json.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/markdown.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/styles/plain.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/actionlint_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/bandit_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/black_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/darglint_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/hadolint_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/prettier_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/ruff_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/formatters/tools/yamllint_formatter.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/models/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/models/core/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/models/core/tool.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/models/core/tool_config.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/models/core/tool_result.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/actionlint/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/actionlint/actionlint_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/actionlint/actionlint_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/black/black_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/black/black_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/darglint/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/darglint/darglint_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/darglint/darglint_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/hadolint/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/hadolint/hadolint_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/hadolint/hadolint_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/prettier/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/prettier/prettier_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/prettier/prettier_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/ruff/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/ruff/ruff_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/ruff/ruff_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/yamllint/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/yamllint/yamllint_issue.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/parsers/yamllint/yamllint_parser.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/core/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/core/tool_base.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/core/tool_manager.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_actionlint.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_bandit.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_black.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_darglint.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_hadolint.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_prettier.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_ruff.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/implementations/tool_yamllint.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/tools/tool_enum.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/ascii_normalize_cli.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/config.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/console_logger.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/formatting.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/output_manager.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/path_utils.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/tool_executor.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro/utils/tool_utils.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro.egg-info/dependency_links.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro.egg-info/entry_points.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro.egg-info/requires.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/lintro.egg-info/top_level.txt +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/setup.cfg +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/Dockerfile.violations +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/actionlint_violations.yml +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/bandit_violations.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/darglint_violations.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/prettier_violations.js +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/ruff_black_e501_wrappable.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/ruff_clean.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/ruff_naming_violations.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/ruff_violations.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/test_samples/yaml_violations.yml +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/cli/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/cli/conftest.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/formatters/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/formatters/conftest.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_bandit_integration.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_ruff_black_policy.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/integration/test_ruff_naming.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_ci_post_pr_comment.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_extract_version.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_github_comment_utilities.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/scripts/test_semantic_release_compute_next.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/test_documentation.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_bandit_command_building.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_bandit_config_hydration.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_bandit_formatter_mapping.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/unit/test_tool_executor_fmt_exclusion.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/utils/__init__.py +0 -0
- {lintro-0.10.0 → lintro-0.11.0}/tests/utils/conftest.py +0 -0
|
@@ -212,6 +212,7 @@ Lintro preserves all Ruff rule categories:
|
|
|
212
212
|
| **pep8-naming** | N | Naming conventions (PEP 8) |
|
|
213
213
|
| **pydocstyle** | D | Docstring style violations |
|
|
214
214
|
| **pyupgrade** | UP | Python upgrade suggestions |
|
|
215
|
+
| **flake8-annotations** | ANN | Type annotation requirements |
|
|
215
216
|
| **flake8-bugbear** | B | Bug detection and complexity |
|
|
216
217
|
| **flake8-comprehensions** | C4 | Comprehension improvements |
|
|
217
218
|
| **flake8-simplify** | SIM | Code simplification suggestions |
|
|
@@ -125,6 +125,7 @@ test_samples/actionlint_violations.yml
|
|
|
125
125
|
test_samples/bandit_violations.py
|
|
126
126
|
test_samples/darglint_violations.py
|
|
127
127
|
test_samples/prettier_violations.js
|
|
128
|
+
test_samples/ruff_annotations_violations.py
|
|
128
129
|
test_samples/ruff_black_e501_wrappable.py
|
|
129
130
|
test_samples/ruff_clean.py
|
|
130
131
|
test_samples/ruff_naming_violations.py
|
|
@@ -146,6 +147,7 @@ tests/integration/test_bandit_integration.py
|
|
|
146
147
|
tests/integration/test_darglint_integration.py
|
|
147
148
|
tests/integration/test_hadolint_integration.py
|
|
148
149
|
tests/integration/test_prettier_integration.py
|
|
150
|
+
tests/integration/test_ruff_annotations.py
|
|
149
151
|
tests/integration/test_ruff_black_policy.py
|
|
150
152
|
tests/integration/test_ruff_integration.py
|
|
151
153
|
tests/integration/test_ruff_naming.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lintro"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.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,8 +65,8 @@ indent-style = "space"
|
|
|
65
65
|
skip-magic-trailing-comma = false
|
|
66
66
|
|
|
67
67
|
[tool.ruff.lint]
|
|
68
|
-
select = [ "E", "F", "W", "I", "COM", "N", "D", "UP",]
|
|
69
|
-
ignore = []
|
|
68
|
+
select = [ "E", "F", "W", "I", "COM", "N", "D", "UP", "ANN",]
|
|
69
|
+
ignore = [ "ANN",]
|
|
70
70
|
|
|
71
71
|
[tool.ruff.pydocstyle]
|
|
72
72
|
convention = "google"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Sample file with flake8-annotations (ANN) violations for testing Ruff.
|
|
2
|
+
|
|
3
|
+
Intentionally violates several ANN-rules, such as:
|
|
4
|
+
- ANN101: missing type annotation for self
|
|
5
|
+
- ANN102: missing type annotation for cls
|
|
6
|
+
- ANN201: missing return type annotation for public function
|
|
7
|
+
- ANN204: missing return type annotation for special method
|
|
8
|
+
- ANN205: missing return type annotation for static method
|
|
9
|
+
- ANN003: missing type annotation for **kwargs
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SampleClass:
|
|
16
|
+
"""Sample class with annotation violations."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, value: int): # ANN101: missing type for self
|
|
19
|
+
self.value = value
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def from_string(cls, s: str): # ANN102: missing type for cls
|
|
23
|
+
return cls(int(s))
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def helper_func(x: int): # ANN205: missing return type
|
|
27
|
+
return x * 2
|
|
28
|
+
|
|
29
|
+
def __str__(self): # ANN204: missing return type for special method
|
|
30
|
+
return f"SampleClass({self.value})"
|
|
31
|
+
|
|
32
|
+
def public_method(self, data: list[str]): # ANN201: missing return type
|
|
33
|
+
return len(data)
|
|
34
|
+
|
|
35
|
+
def kwargs_method(self, **kwargs): # ANN003: missing type for **kwargs
|
|
36
|
+
return kwargs
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def public_function(a: int, b: str): # ANN201: missing return type
|
|
40
|
+
"""Public function without return type annotation."""
|
|
41
|
+
return f"{a}: {b}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def kwargs_function(**kwargs): # ANN003: missing type for **kwargs
|
|
45
|
+
"""Function with kwargs without type annotation."""
|
|
46
|
+
return kwargs
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def nested_function():
|
|
50
|
+
"""Function that returns a nested function."""
|
|
51
|
+
def inner(x: int): # ANN201: missing return type
|
|
52
|
+
return x + 1
|
|
53
|
+
return inner
|
|
@@ -9,7 +9,7 @@ from assertpy import assert_that
|
|
|
9
9
|
from lintro.cli import cli
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def test_cli_help():
|
|
12
|
+
def test_cli_help() -> None:
|
|
13
13
|
"""Test that CLI shows help."""
|
|
14
14
|
from click.testing import CliRunner
|
|
15
15
|
|
|
@@ -19,7 +19,7 @@ def test_cli_help():
|
|
|
19
19
|
assert_that(result.output).contains("Lintro")
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def test_cli_version():
|
|
22
|
+
def test_cli_version() -> None:
|
|
23
23
|
"""Test that CLI shows version."""
|
|
24
24
|
from click.testing import CliRunner
|
|
25
25
|
|
|
@@ -29,7 +29,7 @@ def test_cli_version():
|
|
|
29
29
|
assert_that(result.output.lower()).contains("version")
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def test_cli_commands_registered():
|
|
32
|
+
def test_cli_commands_registered() -> None:
|
|
33
33
|
"""Test that all commands are registered."""
|
|
34
34
|
from click.testing import CliRunner
|
|
35
35
|
|
|
@@ -42,7 +42,7 @@ def test_cli_commands_registered():
|
|
|
42
42
|
assert_that(result.exit_code).is_equal_to(0)
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def test_main_function():
|
|
45
|
+
def test_main_function() -> None:
|
|
46
46
|
"""Test the main function."""
|
|
47
47
|
from click.testing import CliRunner
|
|
48
48
|
|
|
@@ -52,7 +52,7 @@ def test_main_function():
|
|
|
52
52
|
assert_that(result.output).contains("Lintro")
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def test_cli_command_aliases():
|
|
55
|
+
def test_cli_command_aliases() -> None:
|
|
56
56
|
"""Test that command aliases work."""
|
|
57
57
|
from click.testing import CliRunner
|
|
58
58
|
|
|
@@ -65,7 +65,7 @@ def test_cli_command_aliases():
|
|
|
65
65
|
assert_that(result.exit_code).is_equal_to(0)
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def test_cli_with_no_args():
|
|
68
|
+
def test_cli_with_no_args() -> None:
|
|
69
69
|
"""Test CLI with no arguments."""
|
|
70
70
|
from click.testing import CliRunner
|
|
71
71
|
|
|
@@ -75,7 +75,7 @@ def test_cli_with_no_args():
|
|
|
75
75
|
assert_that(result.output).is_equal_to("")
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
def test_main_module_execution():
|
|
78
|
+
def test_main_module_execution() -> None:
|
|
79
79
|
"""Test that __main__.py can be executed directly."""
|
|
80
80
|
with patch.object(sys, "argv", ["lintro", "--help"]):
|
|
81
81
|
import lintro.__main__
|
|
@@ -83,7 +83,7 @@ def test_main_module_execution():
|
|
|
83
83
|
assert_that(lintro.__main__).is_not_none()
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def test_main_module_as_script():
|
|
86
|
+
def test_main_module_as_script() -> None:
|
|
87
87
|
"""Test that __main__.py works when run as a script."""
|
|
88
88
|
result = subprocess.run(
|
|
89
89
|
[sys.executable, "-m", "lintro", "--help"],
|
|
@@ -32,7 +32,7 @@ def _ensure_test_docker_images_built() -> None:
|
|
|
32
32
|
return
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def pytest_collection_modifyitems(config, items):
|
|
35
|
+
def pytest_collection_modifyitems(config, items) -> None:
|
|
36
36
|
"""Optionally skip docker tests locally unless explicitly enabled.
|
|
37
37
|
|
|
38
38
|
If `LINTRO_RUN_DOCKER_TESTS` is not set to "1", mark tests under
|
|
@@ -13,7 +13,7 @@ from lintro.formatters.styles.markdown import MarkdownStyle
|
|
|
13
13
|
from lintro.formatters.styles.plain import PlainStyle
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def test_output_style_abstract():
|
|
16
|
+
def test_output_style_abstract() -> None:
|
|
17
17
|
"""Test that OutputStyle is an abstract base class."""
|
|
18
18
|
from abc import ABC
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ def test_output_style_abstract():
|
|
|
21
21
|
assert_that(hasattr(OutputStyle, "format")).is_true()
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def test_table_descriptor_abstract():
|
|
24
|
+
def test_table_descriptor_abstract() -> None:
|
|
25
25
|
"""Test TableDescriptor is an abstract base class."""
|
|
26
26
|
from abc import ABC
|
|
27
27
|
|
|
@@ -30,13 +30,13 @@ def test_table_descriptor_abstract():
|
|
|
30
30
|
assert_that(hasattr(TableDescriptor, "get_rows")).is_true()
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def test_table_descriptor_methods():
|
|
33
|
+
def test_table_descriptor_methods() -> None:
|
|
34
34
|
"""Test TableDescriptor abstract methods exist."""
|
|
35
35
|
assert_that(callable(TableDescriptor.get_columns)).is_true()
|
|
36
36
|
assert_that(callable(TableDescriptor.get_rows)).is_true()
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def test_csv_style_format():
|
|
39
|
+
def test_csv_style_format() -> None:
|
|
40
40
|
"""Test CSV style formatting."""
|
|
41
41
|
style = CsvStyle()
|
|
42
42
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -45,14 +45,14 @@ def test_csv_style_format():
|
|
|
45
45
|
assert_that(result).contains("val3,val4")
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def test_csv_style_format_empty():
|
|
48
|
+
def test_csv_style_format_empty() -> None:
|
|
49
49
|
"""Test CSV style formatting with empty data."""
|
|
50
50
|
style = CsvStyle()
|
|
51
51
|
result = style.format([], [])
|
|
52
52
|
assert_that(result).is_equal_to("")
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def test_grid_style_format():
|
|
55
|
+
def test_grid_style_format() -> None:
|
|
56
56
|
"""Test grid style formatting."""
|
|
57
57
|
style = GridStyle()
|
|
58
58
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -62,14 +62,14 @@ def test_grid_style_format():
|
|
|
62
62
|
assert_that(result).contains("val2")
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def test_grid_style_format_empty():
|
|
65
|
+
def test_grid_style_format_empty() -> None:
|
|
66
66
|
"""Test grid style formatting with empty data."""
|
|
67
67
|
style = GridStyle()
|
|
68
68
|
result = style.format([], [])
|
|
69
69
|
assert_that(result).is_equal_to("")
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def test_grid_style_format_fallback():
|
|
72
|
+
def test_grid_style_format_fallback() -> None:
|
|
73
73
|
"""Test grid style formatting fallback when tabulate is not available."""
|
|
74
74
|
style = GridStyle()
|
|
75
75
|
with pytest.MonkeyPatch().context() as m:
|
|
@@ -83,7 +83,7 @@ def test_grid_style_format_fallback():
|
|
|
83
83
|
assert_that(result).contains(" | ")
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def test_grid_style_format_fallback_empty():
|
|
86
|
+
def test_grid_style_format_fallback_empty() -> None:
|
|
87
87
|
"""Test grid style formatting fallback with empty data."""
|
|
88
88
|
style = GridStyle()
|
|
89
89
|
with pytest.MonkeyPatch().context() as m:
|
|
@@ -93,7 +93,7 @@ def test_grid_style_format_fallback_empty():
|
|
|
93
93
|
assert_that(result).is_equal_to("")
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
def test_grid_style_format_fallback_single_column():
|
|
96
|
+
def test_grid_style_format_fallback_single_column() -> None:
|
|
97
97
|
"""Test grid style formatting fallback with single column."""
|
|
98
98
|
style = GridStyle()
|
|
99
99
|
with pytest.MonkeyPatch().context() as m:
|
|
@@ -105,7 +105,7 @@ def test_grid_style_format_fallback_single_column():
|
|
|
105
105
|
assert_that(result).contains("val2")
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
def test_html_style_format():
|
|
108
|
+
def test_html_style_format() -> None:
|
|
109
109
|
"""Test HTML style formatting."""
|
|
110
110
|
style = HtmlStyle()
|
|
111
111
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -116,7 +116,7 @@ def test_html_style_format():
|
|
|
116
116
|
assert_that(result).contains("<td>val2</td>")
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def test_json_style_format():
|
|
119
|
+
def test_json_style_format() -> None:
|
|
120
120
|
"""Test JSON style formatting."""
|
|
121
121
|
style = JsonStyle()
|
|
122
122
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -126,7 +126,7 @@ def test_json_style_format():
|
|
|
126
126
|
assert_that(result).contains("val2")
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def test_markdown_style_format():
|
|
129
|
+
def test_markdown_style_format() -> None:
|
|
130
130
|
"""Test markdown style formatting."""
|
|
131
131
|
style = MarkdownStyle()
|
|
132
132
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -135,7 +135,7 @@ def test_markdown_style_format():
|
|
|
135
135
|
assert_that(result).contains("| val3 | val4 |")
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def test_plain_style_format():
|
|
138
|
+
def test_plain_style_format() -> None:
|
|
139
139
|
"""Test plain style formatting."""
|
|
140
140
|
style = PlainStyle()
|
|
141
141
|
result = style.format(["col1", "col2"], [["val1", "val2"], ["val3", "val4"]])
|
|
@@ -145,7 +145,7 @@ def test_plain_style_format():
|
|
|
145
145
|
assert_that(result).contains("val2")
|
|
146
146
|
|
|
147
147
|
|
|
148
|
-
def test_all_styles_produce_output():
|
|
148
|
+
def test_all_styles_produce_output() -> None:
|
|
149
149
|
"""Test that all styles produce some output."""
|
|
150
150
|
styles = [
|
|
151
151
|
CsvStyle(),
|
|
@@ -163,7 +163,7 @@ def test_all_styles_produce_output():
|
|
|
163
163
|
assert_that(len(result) > 0).is_true()
|
|
164
164
|
|
|
165
165
|
|
|
166
|
-
def test_styles_handle_empty_results():
|
|
166
|
+
def test_styles_handle_empty_results() -> None:
|
|
167
167
|
"""Test that all styles handle empty results gracefully."""
|
|
168
168
|
styles = [
|
|
169
169
|
CsvStyle(),
|
|
@@ -33,7 +33,7 @@ def test_files_dir():
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
@pytest.fixture
|
|
36
|
-
def sample_python_file():
|
|
36
|
+
def sample_python_file() -> str:
|
|
37
37
|
"""Provide a sample Python file with violations.
|
|
38
38
|
|
|
39
39
|
Returns:
|
|
@@ -50,7 +50,7 @@ def sample_python_file():
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
@pytest.fixture
|
|
53
|
-
def sample_js_file():
|
|
53
|
+
def sample_js_file() -> str:
|
|
54
54
|
"""Provide a sample JavaScript file with formatting issues.
|
|
55
55
|
|
|
56
56
|
Returns:
|
|
@@ -33,7 +33,7 @@ def actionlint_available() -> bool:
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
@pytest.mark.actionlint
|
|
36
|
-
def test_actionlint_available():
|
|
36
|
+
def test_actionlint_available() -> None:
|
|
37
37
|
"""Skip the suite if actionlint is not present locally.
|
|
38
38
|
|
|
39
39
|
Ensures local runs behave like CI (which always has actionlint in Docker),
|
|
@@ -47,7 +47,7 @@ SAMPLE_BAD = Path("test_samples/actionlint_violations.yml")
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
@pytest.mark.actionlint
|
|
50
|
-
def test_actionlint_reports_violations(tmp_path):
|
|
50
|
+
def test_actionlint_reports_violations(tmp_path) -> None:
|
|
51
51
|
"""Assert that Lintro detects violations reported by actionlint.
|
|
52
52
|
|
|
53
53
|
Args:
|
|
@@ -71,7 +71,7 @@ def test_actionlint_reports_violations(tmp_path):
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
@pytest.mark.actionlint
|
|
74
|
-
def test_actionlint_no_files(tmp_path):
|
|
74
|
+
def test_actionlint_no_files(tmp_path) -> None:
|
|
75
75
|
"""Assert that Lintro succeeds when no workflow files are present.
|
|
76
76
|
|
|
77
77
|
Args:
|
|
@@ -65,7 +65,7 @@ def _ensure_darglint_cli_available() -> None:
|
|
|
65
65
|
pytest.skip("darglint CLI not installed/runnable; skipping direct CLI test")
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def test_darglint_reports_violations_direct(tmp_path):
|
|
68
|
+
def test_darglint_reports_violations_direct(tmp_path) -> None:
|
|
69
69
|
"""Darglint CLI: Should detect and report violations in a sample file.
|
|
70
70
|
|
|
71
71
|
Args:
|
|
@@ -82,7 +82,7 @@ def test_darglint_reports_violations_direct(tmp_path):
|
|
|
82
82
|
assert "DAR" in output, "Darglint output should contain error codes."
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def test_darglint_reports_violations_through_lintro(tmp_path):
|
|
85
|
+
def test_darglint_reports_violations_through_lintro(tmp_path) -> None:
|
|
86
86
|
"""Lintro DarglintTool: Should detect and report violations in a sample file.
|
|
87
87
|
|
|
88
88
|
Args:
|
|
@@ -111,7 +111,7 @@ def test_darglint_reports_violations_through_lintro(tmp_path):
|
|
|
111
111
|
), "Lintro DarglintTool output should contain error codes."
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
def test_darglint_output_consistency_direct_vs_lintro(tmp_path):
|
|
114
|
+
def test_darglint_output_consistency_direct_vs_lintro(tmp_path) -> None:
|
|
115
115
|
"""Darglint CLI vs Lintro: Should produce consistent results for the same file.
|
|
116
116
|
|
|
117
117
|
Args:
|
|
@@ -137,7 +137,7 @@ def test_darglint_output_consistency_direct_vs_lintro(tmp_path):
|
|
|
137
137
|
# Optionally compare error codes if output format is stable
|
|
138
138
|
|
|
139
139
|
|
|
140
|
-
def test_darglint_fix_method_not_implemented(tmp_path):
|
|
140
|
+
def test_darglint_fix_method_not_implemented(tmp_path) -> None:
|
|
141
141
|
"""Lintro DarglintTool: .fix() should raise NotImplementedError.
|
|
142
142
|
|
|
143
143
|
Args:
|
|
@@ -69,7 +69,7 @@ def run_hadolint_directly(file_path: Path) -> tuple[bool, str, int]:
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
@pytest.mark.hadolint
|
|
72
|
-
def test_hadolint_available():
|
|
72
|
+
def test_hadolint_available() -> None:
|
|
73
73
|
"""Check if hadolint is available in PATH."""
|
|
74
74
|
try:
|
|
75
75
|
result = subprocess.run(
|
|
@@ -85,7 +85,7 @@ def test_hadolint_available():
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
@pytest.mark.hadolint
|
|
88
|
-
def test_hadolint_reports_violations_direct(tmp_path):
|
|
88
|
+
def test_hadolint_reports_violations_direct(tmp_path) -> None:
|
|
89
89
|
"""Hadolint CLI: Should detect and report violations in a sample file.
|
|
90
90
|
|
|
91
91
|
Args:
|
|
@@ -115,7 +115,7 @@ def test_hadolint_reports_violations_direct(tmp_path):
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
@pytest.mark.hadolint
|
|
118
|
-
def test_hadolint_reports_violations_through_lintro(tmp_path):
|
|
118
|
+
def test_hadolint_reports_violations_through_lintro(tmp_path) -> None:
|
|
119
119
|
"""Lintro HadolintTool: Should detect and report violations in a sample file.
|
|
120
120
|
|
|
121
121
|
Args:
|
|
@@ -145,7 +145,7 @@ def test_hadolint_reports_violations_through_lintro(tmp_path):
|
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
@pytest.mark.hadolint
|
|
148
|
-
def test_hadolint_output_consistency_direct_vs_lintro(tmp_path):
|
|
148
|
+
def test_hadolint_output_consistency_direct_vs_lintro(tmp_path) -> None:
|
|
149
149
|
"""Hadolint CLI vs Lintro: Should produce consistent results for the same file.
|
|
150
150
|
|
|
151
151
|
Args:
|
|
@@ -184,7 +184,7 @@ def test_hadolint_output_consistency_direct_vs_lintro(tmp_path):
|
|
|
184
184
|
|
|
185
185
|
|
|
186
186
|
@pytest.mark.hadolint
|
|
187
|
-
def test_hadolint_with_ignore_rules(tmp_path):
|
|
187
|
+
def test_hadolint_with_ignore_rules(tmp_path) -> None:
|
|
188
188
|
"""Lintro HadolintTool: Should properly ignore specified rules.
|
|
189
189
|
|
|
190
190
|
Args:
|
|
@@ -206,7 +206,7 @@ def test_hadolint_with_ignore_rules(tmp_path):
|
|
|
206
206
|
|
|
207
207
|
|
|
208
208
|
@pytest.mark.hadolint
|
|
209
|
-
def test_hadolint_fix_method_not_implemented(tmp_path):
|
|
209
|
+
def test_hadolint_fix_method_not_implemented(tmp_path) -> None:
|
|
210
210
|
"""Lintro HadolintTool: .fix() should raise NotImplementedError.
|
|
211
211
|
|
|
212
212
|
Args:
|
|
@@ -225,7 +225,7 @@ def test_hadolint_fix_method_not_implemented(tmp_path):
|
|
|
225
225
|
|
|
226
226
|
|
|
227
227
|
@pytest.mark.hadolint
|
|
228
|
-
def test_hadolint_empty_directory(tmp_path):
|
|
228
|
+
def test_hadolint_empty_directory(tmp_path) -> None:
|
|
229
229
|
"""Lintro HadolintTool: Should handle empty directories gracefully.
|
|
230
230
|
|
|
231
231
|
Args:
|
|
@@ -243,7 +243,7 @@ def test_hadolint_empty_directory(tmp_path):
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
@pytest.mark.hadolint
|
|
246
|
-
def test_hadolint_parser_validation(tmp_path):
|
|
246
|
+
def test_hadolint_parser_validation(tmp_path) -> None:
|
|
247
247
|
"""Test that hadolint parser correctly parses output.
|
|
248
248
|
|
|
249
249
|
Args:
|
|
@@ -68,7 +68,7 @@ def run_prettier_directly(
|
|
|
68
68
|
return success, full_output, issues_count
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
def test_prettier_reports_violations_direct(temp_prettier_file):
|
|
71
|
+
def test_prettier_reports_violations_direct(temp_prettier_file) -> None:
|
|
72
72
|
"""Prettier CLI: Should detect and report violations in a sample file.
|
|
73
73
|
|
|
74
74
|
Args:
|
|
@@ -84,7 +84,7 @@ def test_prettier_reports_violations_direct(temp_prettier_file):
|
|
|
84
84
|
assert has_warnings, "Prettier output should contain warning indicators."
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
def test_prettier_reports_violations_through_lintro(temp_prettier_file):
|
|
87
|
+
def test_prettier_reports_violations_through_lintro(temp_prettier_file) -> None:
|
|
88
88
|
"""Lintro PrettierTool: Should detect and report violations in a sample file.
|
|
89
89
|
|
|
90
90
|
Args:
|
|
@@ -109,7 +109,7 @@ def test_prettier_reports_violations_through_lintro(temp_prettier_file):
|
|
|
109
109
|
assert has_warnings, "Lintro PrettierTool output should contain warning indicators."
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
def test_prettier_fix_method(temp_prettier_file):
|
|
112
|
+
def test_prettier_fix_method(temp_prettier_file) -> None:
|
|
113
113
|
"""Lintro PrettierTool: Should fix formatting issues.
|
|
114
114
|
|
|
115
115
|
Args:
|
|
@@ -147,7 +147,7 @@ def test_prettier_fix_method(temp_prettier_file):
|
|
|
147
147
|
assert final_result.issues_count == 0, "Should have no issues after fixing"
|
|
148
148
|
|
|
149
149
|
|
|
150
|
-
def test_prettier_output_consistency_direct_vs_lintro(temp_prettier_file):
|
|
150
|
+
def test_prettier_output_consistency_direct_vs_lintro(temp_prettier_file) -> None:
|
|
151
151
|
"""Prettier CLI vs Lintro: Should produce consistent results for the same file.
|
|
152
152
|
|
|
153
153
|
Args:
|
|
@@ -178,7 +178,7 @@ def test_prettier_output_consistency_direct_vs_lintro(temp_prettier_file):
|
|
|
178
178
|
)
|
|
179
179
|
|
|
180
180
|
|
|
181
|
-
def test_prettier_fix_sets_issues_for_table(temp_prettier_file):
|
|
181
|
+
def test_prettier_fix_sets_issues_for_table(temp_prettier_file) -> None:
|
|
182
182
|
"""PrettierTool.fix should populate issues for table rendering.
|
|
183
183
|
|
|
184
184
|
Args:
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Integration tests for Ruff flake8-annotations (ANN) rule family."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import shutil
|
|
7
|
+
import tempfile
|
|
8
|
+
|
|
9
|
+
from assertpy import assert_that
|
|
10
|
+
|
|
11
|
+
from lintro.tools.implementations.tool_ruff import RuffTool
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_annotations_rules_detected() -> None:
|
|
15
|
+
"""Ensure Ruff reports ANN-family violations on a known sample file."""
|
|
16
|
+
sample = os.path.abspath("test_samples/ruff_annotations_violations.py")
|
|
17
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
18
|
+
test_file = os.path.join(tmp, "ruff_annotations_case.py")
|
|
19
|
+
shutil.copy(sample, test_file)
|
|
20
|
+
|
|
21
|
+
ruff = RuffTool()
|
|
22
|
+
ruff.set_options(select=["ANN"]) # only ANN rules
|
|
23
|
+
result = ruff.check([test_file])
|
|
24
|
+
|
|
25
|
+
assert_that(result.success).is_false()
|
|
26
|
+
codes = [getattr(i, "code", "") for i in (result.issues or [])]
|
|
27
|
+
# Expect several representative ANN-codes
|
|
28
|
+
assert_that(any(code.startswith("ANN") for code in codes)).is_true()
|
|
29
|
+
assert_that(
|
|
30
|
+
any(
|
|
31
|
+
code in {"ANN101", "ANN102", "ANN201", "ANN204", "ANN205", "ANN003"}
|
|
32
|
+
for code in codes
|
|
33
|
+
),
|
|
34
|
+
).is_true()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_annotations_rules_with_other_rules() -> None:
|
|
38
|
+
"""Ensure ANN rules work alongside other rule families."""
|
|
39
|
+
sample = os.path.abspath("test_samples/ruff_annotations_violations.py")
|
|
40
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
41
|
+
test_file = os.path.join(tmp, "ruff_annotations_mixed.py")
|
|
42
|
+
shutil.copy(sample, test_file)
|
|
43
|
+
|
|
44
|
+
ruff = RuffTool()
|
|
45
|
+
ruff.set_options(select=["ANN", "F"]) # ANN + pyflakes errors
|
|
46
|
+
result = ruff.check([test_file])
|
|
47
|
+
|
|
48
|
+
assert_that(result.success).is_false()
|
|
49
|
+
codes = [getattr(i, "code", "") for i in (result.issues or [])]
|
|
50
|
+
# Should have ANN codes (F codes may not be present in this sample)
|
|
51
|
+
assert_that(any(code.startswith("ANN") for code in codes)).is_true()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_annotations_rules_fix_capability() -> None:
|
|
55
|
+
"""Test that ANN rules can be fixed automatically where possible."""
|
|
56
|
+
sample = os.path.abspath("test_samples/ruff_annotations_violations.py")
|
|
57
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
58
|
+
test_file = os.path.join(tmp, "ruff_annotations_fix.py")
|
|
59
|
+
shutil.copy(sample, test_file)
|
|
60
|
+
|
|
61
|
+
ruff = RuffTool()
|
|
62
|
+
ruff.set_options(select=["ANN"])
|
|
63
|
+
|
|
64
|
+
# Check initial issues
|
|
65
|
+
initial_result = ruff.check([test_file])
|
|
66
|
+
initial_count = len(initial_result.issues or [])
|
|
67
|
+
|
|
68
|
+
# Apply fixes
|
|
69
|
+
ruff.fix([test_file])
|
|
70
|
+
|
|
71
|
+
# Check remaining issues after fix
|
|
72
|
+
final_result = ruff.check([test_file])
|
|
73
|
+
final_count = len(final_result.issues or [])
|
|
74
|
+
|
|
75
|
+
# Some issues should be fixed (though ANN rules are often not auto-fixable)
|
|
76
|
+
# We mainly verify the fix process doesn't crash and reduces issue count
|
|
77
|
+
assert_that(initial_count).is_greater_than_or_equal_to(final_count)
|
|
78
|
+
# Fix result may be False if issues remain, which is expected for ANN rules
|