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.
- {lintro-0.8.0/lintro.egg-info → lintro-0.9.0}/PKG-INFO +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/assets/images/coverage-badge.svg +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/lintro/__init__.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/list_tools.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/actionlint_parser.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/tool_base.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_ruff.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0/lintro.egg-info}/PKG-INFO +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/pyproject.toml +2 -2
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_hadolint_integration.py +14 -17
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_ruff_integration.py +4 -4
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_yamllint_integration.py +17 -21
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_ci_post_pr_comment.py +1 -1
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_ghcr_prune_untagged.py +2 -2
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_script_environment.py +8 -8
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_shell_scripts.py +7 -7
- {lintro-0.8.0 → lintro-0.9.0}/tests/test_documentation.py +9 -9
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ascii_normalize.py +2 -2
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils.py +3 -3
- {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_output_manager.py +2 -2
- {lintro-0.8.0 → lintro-0.9.0}/LICENSE +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/MANIFEST.in +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/README.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/assets/images/lintro.png +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/README.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/configuration.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/contributing.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/coverage-setup.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/docker.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/getting-started.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/github-integration.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/lintro-self-use.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/security/assurance.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/security/requirements.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/style-guide.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/README.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/actionlint-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/bandit-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/black-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/darglint-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/hadolint-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/prettier-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/ruff-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/docs/tool-analysis/yamllint-analysis.md +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/__main__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/ascii-art/fail.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/ascii-art/success.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/check.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/cli_utils/commands/format.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/action.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/darglint_strictness.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/group_by.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/hadolint_enums.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/output_format.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/tool_name.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/tool_type.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/enums/yamllint_format.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/exceptions/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/exceptions/errors.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/output_style.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/core/table_descriptor.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/csv.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/grid.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/html.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/json.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/markdown.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/styles/plain.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/actionlint_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/bandit_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/black_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/darglint_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/hadolint_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/prettier_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/ruff_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/formatters/tools/yamllint_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/models/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool_config.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/models/core/tool_result.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/actionlint/actionlint_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/black/black_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/black/black_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/darglint_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/darglint/darglint_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/hadolint_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/hadolint/hadolint_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/prettier_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/prettier/prettier_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/ruff_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/ruff/ruff_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/yamllint_issue.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/parsers/yamllint/yamllint_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/core/tool_manager.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_actionlint.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_bandit.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_black.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_darglint.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_hadolint.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_prettier.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/implementations/tool_yamllint.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/tools/tool_enum.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/ascii_normalize_cli.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/config.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/console_logger.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/formatting.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/output_manager.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/path_utils.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/tool_executor.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro/utils/tool_utils.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/SOURCES.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/dependency_links.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/entry_points.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/requires.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/lintro.egg-info/top_level.txt +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/setup.cfg +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/Dockerfile.violations +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/actionlint_violations.yml +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/bandit_violations.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/darglint_violations.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/prettier_violations.js +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_black_e501_wrappable.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_clean.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/ruff_violations.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/test_samples/yaml_violations.yml +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/cli/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/cli/conftest.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/cli/test_cli.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/conftest.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/conftest.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/formatters/test_formatters.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/conftest.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_actionlint_integration.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_bandit_integration.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_darglint_integration.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_prettier_integration.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/integration/test_ruff_black_policy.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_delete_previous_lintro_comments.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_extract_version.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_github_comment_utilities.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/scripts/test_semantic_release_compute_next.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_command_building.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_config_hydration.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_formatter_mapping.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_bandit_parsing.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_formatter.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_parser.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_tool.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_black_tool_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_commands.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_commands_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_cli_programmatic.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_compatibility_ruff_black.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_config_loader.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_config_loader_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_console_logger.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_console_logger_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_enums_and_normalizers.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_exceptions.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_formatters_tables.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_output_manager_reports.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_parsers_actionlint.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ruff_parser_additional.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_ruff_parser_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_subprocess_validator.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_base_subprocess.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_fmt_exclusion.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_executor_post_checks.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_manager.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils_fallbacks.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/unit/test_tool_utils_more.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/utils/__init__.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/utils/conftest.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_formatting.py +0 -0
- {lintro-0.8.0 → lintro-0.9.0}/tests/utils/test_path_utils.py +0 -0
|
@@ -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="#
|
|
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">
|
|
@@ -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
|
|
112
|
+
except OSError as e:
|
|
113
113
|
error_msg = f"Error writing to file {output}: {e}"
|
|
114
114
|
click.echo(error_msg, err=True)
|
|
@@ -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,
|
|
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,
|
|
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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lintro"
|
|
7
|
-
version = "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
|
|
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
|
|
50
|
-
|
|
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(
|
|
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
|
|
105
|
-
|
|
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
|
|
134
|
-
|
|
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
|
|
163
|
-
|
|
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
|
|
175
|
-
|
|
176
|
-
|
|
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
|
|
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(
|
|
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:
|
|
428
|
-
|
|
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
|
|
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
|
|
50
|
-
|
|
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(
|
|
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
|
|
106
|
-
|
|
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
|
|
135
|
-
|
|
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
|
|
168
|
-
|
|
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
|
|
172
|
-
|
|
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:
|
|
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
|
|
185
|
-
|
|
186
|
-
|
|
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
|
|
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) ->
|
|
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) ->
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
580
|
+
with open(script) as f:
|
|
581
581
|
first_line = f.readline().strip()
|
|
582
582
|
if first_line == "#!/bin/sh":
|
|
583
|
-
with open(script
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
79
|
-
assert_that(any(
|
|
80
|
-
assert_that(any(
|
|
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(
|
|
166
|
-
assert_that(any(
|
|
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
|
|
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
|