lintro 0.13.2__tar.gz → 0.13.3__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.13.2/lintro.egg-info → lintro-0.13.3}/PKG-INFO +1 -1
- {lintro-0.13.2 → lintro-0.13.3}/assets/images/coverage-badge.svg +2 -2
- {lintro-0.13.2 → lintro-0.13.3}/lintro/__init__.py +1 -1
- lintro-0.13.3/lintro/parsers/__init__.py +72 -0
- lintro-0.13.3/lintro/parsers/bandit/__init__.py +6 -0
- lintro-0.13.3/lintro/parsers/bandit/bandit_issue.py +49 -0
- lintro-0.13.3/lintro/parsers/bandit/bandit_parser.py +99 -0
- {lintro-0.13.2 → lintro-0.13.3/lintro.egg-info}/PKG-INFO +1 -1
- {lintro-0.13.2 → lintro-0.13.3}/lintro.egg-info/SOURCES.txt +3 -0
- {lintro-0.13.2 → lintro-0.13.3}/pyproject.toml +2 -2
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_package_imports.py +72 -0
- lintro-0.13.2/lintro/parsers/__init__.py +0 -21
- {lintro-0.13.2 → lintro-0.13.3}/LICENSE +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/MANIFEST.in +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/README.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/assets/images/lintro.png +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/README.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/configuration.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/contributing.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/coverage-setup.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/docker.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/getting-started.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/github-integration.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/lintro-self-use.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/security/assurance.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/security/requirements.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/style-guide.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/README.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/actionlint-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/bandit-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/black-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/darglint-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/hadolint-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/prettier-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/ruff-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/docs/tool-analysis/yamllint-analysis.md +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/__main__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/ascii-art/fail.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/ascii-art/success.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli_utils/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli_utils/commands/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli_utils/commands/check.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli_utils/commands/format.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/cli_utils/commands/list_tools.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/action.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/darglint_strictness.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/group_by.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/hadolint_enums.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/output_format.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/tool_name.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/tool_type.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/enums/yamllint_format.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/exceptions/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/exceptions/errors.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/core/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/core/output_style.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/core/table_descriptor.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/csv.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/grid.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/html.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/json.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/markdown.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/styles/plain.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/actionlint_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/bandit_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/black_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/darglint_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/hadolint_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/prettier_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/ruff_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/formatters/tools/yamllint_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/models/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/models/core/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/models/core/tool.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/models/core/tool_config.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/models/core/tool_result.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/actionlint/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/actionlint/actionlint_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/actionlint/actionlint_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/black/black_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/black/black_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/darglint/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/darglint/darglint_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/darglint/darglint_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/hadolint/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/hadolint/hadolint_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/hadolint/hadolint_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/prettier/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/prettier/prettier_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/prettier/prettier_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/ruff/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/ruff/ruff_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/ruff/ruff_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/yamllint/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/yamllint/yamllint_issue.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/parsers/yamllint/yamllint_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/core/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/core/tool_base.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/core/tool_manager.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_actionlint.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_bandit.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_black.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_darglint.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_hadolint.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_prettier.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_ruff.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/implementations/tool_yamllint.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/tools/tool_enum.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/ascii_normalize_cli.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/config.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/console_logger.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/formatting.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/output_manager.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/path_utils.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/tool_executor.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro/utils/tool_utils.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro.egg-info/dependency_links.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro.egg-info/entry_points.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro.egg-info/requires.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/lintro.egg-info/top_level.txt +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/setup.cfg +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/Dockerfile.violations +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/actionlint_violations.yml +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/bandit_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/darglint_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/prettier_violations.js +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_annotations_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_black_e501_wrappable.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_bugbear_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_c4_comprehensions_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_clean.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_naming_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_sim_simplify_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/ruff_violations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/test_samples/yaml_violations.yml +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/cli/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/cli/conftest.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/cli/test_cli.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/conftest.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/formatters/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/formatters/conftest.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/formatters/test_formatters.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/conftest.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_actionlint_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_bandit_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_built_package.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_darglint_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_hadolint_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_prettier_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_additional_coverage.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_annotations.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_black_policy.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_bugbear.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_ruff_naming.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/integration/test_yamllint_integration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_ci_post_pr_comment.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_delete_previous_lintro_comments.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_extract_version.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_ghcr_prune_untagged.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_github_comment_utilities.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_script_environment.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_semantic_release_compute_next.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/scripts/test_shell_scripts.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/test_documentation.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_ascii_normalize.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_bandit_command_building.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_bandit_config_hydration.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_bandit_formatter_mapping.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_bandit_parsing.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_black_formatter.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_black_parser.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_black_tool.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_black_tool_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_cli_commands.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_cli_commands_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_cli_programmatic.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_compatibility_ruff_black.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_config_loader.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_config_loader_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_console_logger.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_console_logger_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_enums_and_normalizers.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_exceptions.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_formatters_tables.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_output_manager_reports.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_parsers_actionlint.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_ruff_parser_additional.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_ruff_parser_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_subprocess_validator.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_base_subprocess.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_executor.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_executor_fmt_exclusion.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_executor_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_executor_post_checks.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_manager.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_utils.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_utils_fallbacks.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/unit/test_tool_utils_more.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/utils/__init__.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/utils/conftest.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/utils/test_formatting.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/utils/test_output_manager.py +0 -0
- {lintro-0.13.2 → lintro-0.13.3}/tests/utils/test_path_utils.py +0 -0
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
|
16
16
|
<text x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">coverage</text>
|
|
17
17
|
<text x="325" y="140" transform="scale(.1)" textLength="530">coverage</text>
|
|
18
|
-
<text x="800" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="260">84.
|
|
19
|
-
<text x="800" y="140" transform="scale(.1)" textLength="260">84.
|
|
18
|
+
<text x="800" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="260">84.7%</text>
|
|
19
|
+
<text x="800" y="140" transform="scale(.1)" textLength="260">84.7%</text>
|
|
20
20
|
</g>
|
|
21
21
|
</svg>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Parser modules for Lintro tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib import import_module
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
# Type checking imports
|
|
10
|
+
from lintro.parsers import (
|
|
11
|
+
actionlint,
|
|
12
|
+
bandit,
|
|
13
|
+
darglint,
|
|
14
|
+
hadolint,
|
|
15
|
+
prettier,
|
|
16
|
+
ruff,
|
|
17
|
+
yamllint,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"actionlint",
|
|
22
|
+
"bandit",
|
|
23
|
+
"darglint",
|
|
24
|
+
"hadolint",
|
|
25
|
+
"prettier",
|
|
26
|
+
"ruff",
|
|
27
|
+
"yamllint",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# Lazy-load parser submodules to avoid circular imports
|
|
31
|
+
_SUBMODULES = {
|
|
32
|
+
"actionlint",
|
|
33
|
+
"bandit",
|
|
34
|
+
"darglint",
|
|
35
|
+
"hadolint",
|
|
36
|
+
"prettier",
|
|
37
|
+
"ruff",
|
|
38
|
+
"yamllint",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def __getattr__(name: str) -> object:
|
|
43
|
+
"""Lazy-load parser submodules to avoid circular import issues.
|
|
44
|
+
|
|
45
|
+
This function is called when an attribute is accessed that doesn't exist
|
|
46
|
+
in the module. It allows accessing parser submodules without eagerly
|
|
47
|
+
importing them all at package initialization time.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
name: The name of the attribute being accessed.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
The imported submodule.
|
|
54
|
+
|
|
55
|
+
Raises:
|
|
56
|
+
AttributeError: If the requested name is not a known submodule.
|
|
57
|
+
"""
|
|
58
|
+
if name in _SUBMODULES:
|
|
59
|
+
module = import_module(f".{name}", __package__)
|
|
60
|
+
# Cache the module in this module's namespace for future access
|
|
61
|
+
globals()[name] = module
|
|
62
|
+
return module
|
|
63
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def __dir__() -> list[str]:
|
|
67
|
+
"""Return list of available attributes for this module.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
List of submodule names and other module attributes.
|
|
71
|
+
"""
|
|
72
|
+
return list(__all__)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Bandit issue model for security vulnerabilities."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class BanditIssue:
|
|
9
|
+
"""Represents a security issue found by Bandit.
|
|
10
|
+
|
|
11
|
+
Attributes:
|
|
12
|
+
file: str: Path to the file containing the issue.
|
|
13
|
+
line: int: Line number where the issue was found.
|
|
14
|
+
col_offset: int: Column offset of the issue.
|
|
15
|
+
issue_severity: str: Severity level (LOW, MEDIUM, HIGH).
|
|
16
|
+
issue_confidence: str: Confidence level (LOW, MEDIUM, HIGH).
|
|
17
|
+
test_id: str: Bandit test ID (e.g., B602, B301).
|
|
18
|
+
test_name: str: Name of the test that found the issue.
|
|
19
|
+
issue_text: str: Description of the security issue.
|
|
20
|
+
more_info: str: URL with more information about the issue.
|
|
21
|
+
cwe: dict[str, Any] | None: CWE (Common Weakness Enumeration) information.
|
|
22
|
+
code: str: Code snippet containing the issue.
|
|
23
|
+
line_range: list[int]: Range of lines containing the issue.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
file: str
|
|
27
|
+
line: int
|
|
28
|
+
col_offset: int
|
|
29
|
+
issue_severity: str
|
|
30
|
+
issue_confidence: str
|
|
31
|
+
test_id: str
|
|
32
|
+
test_name: str
|
|
33
|
+
issue_text: str
|
|
34
|
+
more_info: str
|
|
35
|
+
cwe: dict[str, Any] | None = None
|
|
36
|
+
code: str | None = None
|
|
37
|
+
line_range: list[int] | None = None
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def message(self) -> str:
|
|
41
|
+
"""Get a human-readable message for the issue.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: Formatted issue message.
|
|
45
|
+
"""
|
|
46
|
+
return (
|
|
47
|
+
f"[{self.test_id}:{self.test_name}] {self.issue_severity} severity, "
|
|
48
|
+
f"{self.issue_confidence} confidence: {self.issue_text}"
|
|
49
|
+
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Bandit output parser for security issues."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from loguru import logger
|
|
6
|
+
|
|
7
|
+
from lintro.parsers.bandit.bandit_issue import BanditIssue
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_bandit_output(bandit_data: dict[str, Any]) -> list[BanditIssue]:
|
|
11
|
+
"""Parse Bandit JSON output into BanditIssue objects.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
bandit_data: dict[str, Any]: JSON data from Bandit output.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
list[BanditIssue]: List of parsed security issues.
|
|
18
|
+
|
|
19
|
+
Raises:
|
|
20
|
+
ValueError: If the bandit data structure is invalid.
|
|
21
|
+
"""
|
|
22
|
+
if not isinstance(bandit_data, dict):
|
|
23
|
+
raise ValueError("Bandit data must be a dictionary")
|
|
24
|
+
|
|
25
|
+
results = bandit_data.get("results", [])
|
|
26
|
+
if not isinstance(results, list):
|
|
27
|
+
raise ValueError("Bandit results must be a list")
|
|
28
|
+
|
|
29
|
+
issues: list[BanditIssue] = []
|
|
30
|
+
|
|
31
|
+
for result in results:
|
|
32
|
+
if not isinstance(result, dict):
|
|
33
|
+
continue
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
filename = result.get("filename", "")
|
|
37
|
+
line_number = result.get("line_number", 0)
|
|
38
|
+
col_offset = result.get("col_offset", 0)
|
|
39
|
+
issue_severity = result.get("issue_severity", "UNKNOWN")
|
|
40
|
+
issue_confidence = result.get("issue_confidence", "UNKNOWN")
|
|
41
|
+
test_id = result.get("test_id", "")
|
|
42
|
+
test_name = result.get("test_name", "")
|
|
43
|
+
issue_text = result.get("issue_text", "")
|
|
44
|
+
more_info = result.get("more_info", "")
|
|
45
|
+
cwe = result.get("issue_cwe")
|
|
46
|
+
code = result.get("code")
|
|
47
|
+
line_range = result.get("line_range")
|
|
48
|
+
|
|
49
|
+
# Validate critical fields; skip malformed entries
|
|
50
|
+
if not isinstance(filename, str):
|
|
51
|
+
logger.warning("Skipping issue with non-string filename")
|
|
52
|
+
continue
|
|
53
|
+
if not isinstance(line_number, int):
|
|
54
|
+
logger.warning("Skipping issue with non-integer line_number")
|
|
55
|
+
continue
|
|
56
|
+
if not isinstance(col_offset, int):
|
|
57
|
+
col_offset = 0
|
|
58
|
+
|
|
59
|
+
sev = (
|
|
60
|
+
str(issue_severity).upper() if issue_severity is not None else "UNKNOWN"
|
|
61
|
+
)
|
|
62
|
+
conf = (
|
|
63
|
+
str(issue_confidence).upper()
|
|
64
|
+
if issue_confidence is not None
|
|
65
|
+
else "UNKNOWN"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
test_id = test_id if isinstance(test_id, str) else ""
|
|
69
|
+
test_name = test_name if isinstance(test_name, str) else ""
|
|
70
|
+
issue_text = issue_text if isinstance(issue_text, str) else ""
|
|
71
|
+
more_info = more_info if isinstance(more_info, str) else ""
|
|
72
|
+
|
|
73
|
+
# Normalize line_range to list[int] when provided
|
|
74
|
+
if isinstance(line_range, list):
|
|
75
|
+
line_range = [x for x in line_range if isinstance(x, int)] or None
|
|
76
|
+
else:
|
|
77
|
+
line_range = None
|
|
78
|
+
|
|
79
|
+
issue = BanditIssue(
|
|
80
|
+
file=filename,
|
|
81
|
+
line=line_number,
|
|
82
|
+
col_offset=col_offset,
|
|
83
|
+
issue_severity=sev,
|
|
84
|
+
issue_confidence=conf,
|
|
85
|
+
test_id=test_id,
|
|
86
|
+
test_name=test_name,
|
|
87
|
+
issue_text=issue_text,
|
|
88
|
+
more_info=more_info,
|
|
89
|
+
cwe=cwe if isinstance(cwe, dict) else None,
|
|
90
|
+
code=code if isinstance(code, str) else None,
|
|
91
|
+
line_range=line_range,
|
|
92
|
+
)
|
|
93
|
+
issues.append(issue)
|
|
94
|
+
except (KeyError, TypeError, ValueError) as e:
|
|
95
|
+
# Log warning but continue processing other issues
|
|
96
|
+
logger.warning(f"Failed to parse bandit issue: {e}")
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
return issues
|
|
@@ -80,6 +80,9 @@ lintro/parsers/__init__.py
|
|
|
80
80
|
lintro/parsers/actionlint/__init__.py
|
|
81
81
|
lintro/parsers/actionlint/actionlint_issue.py
|
|
82
82
|
lintro/parsers/actionlint/actionlint_parser.py
|
|
83
|
+
lintro/parsers/bandit/__init__.py
|
|
84
|
+
lintro/parsers/bandit/bandit_issue.py
|
|
85
|
+
lintro/parsers/bandit/bandit_parser.py
|
|
83
86
|
lintro/parsers/black/black_issue.py
|
|
84
87
|
lintro/parsers/black/black_parser.py
|
|
85
88
|
lintro/parsers/darglint/__init__.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lintro"
|
|
7
|
-
version = "0.13.
|
|
7
|
+
version = "0.13.3"
|
|
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",]
|
|
@@ -38,7 +38,7 @@ Documentation = "https://github.com/TurboCoder13/py-lintro/docs"
|
|
|
38
38
|
Source = "https://github.com/TurboCoder13/py-lintro"
|
|
39
39
|
|
|
40
40
|
[tool.setuptools]
|
|
41
|
-
packages = [ "lintro", "lintro.cli_utils", "lintro.cli_utils.commands", "lintro.enums", "lintro.exceptions", "lintro.formatters", "lintro.formatters.core", "lintro.formatters.styles", "lintro.formatters.tools", "lintro.models", "lintro.models.core", "lintro.parsers", "lintro.parsers.
|
|
41
|
+
packages = [ "lintro", "lintro.cli_utils", "lintro.cli_utils.commands", "lintro.enums", "lintro.exceptions", "lintro.formatters", "lintro.formatters.core", "lintro.formatters.styles", "lintro.formatters.tools", "lintro.models", "lintro.models.core", "lintro.parsers", "lintro.parsers.actionlint", "lintro.parsers.bandit", "lintro.parsers.black", "lintro.parsers.darglint", "lintro.parsers.hadolint", "lintro.parsers.prettier", "lintro.parsers.ruff", "lintro.parsers.yamllint", "lintro.tools", "lintro.tools.core", "lintro.tools.implementations", "lintro.utils",]
|
|
42
42
|
|
|
43
43
|
[tool.semantic_release]
|
|
44
44
|
branch = "main"
|
|
@@ -13,6 +13,8 @@ is installed as a built distribution. However, these tests serve as:
|
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
def test_main_package_import() -> None:
|
|
18
20
|
"""Test that the main lintro package can be imported."""
|
|
@@ -148,3 +150,73 @@ def test_cross_package_imports() -> None:
|
|
|
148
150
|
assert bandit is not None
|
|
149
151
|
assert BanditTool is not None
|
|
150
152
|
assert BanditTableDescriptor is not None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_bandit_parser_direct_import() -> None:
|
|
156
|
+
"""Test that bandit parser can be imported directly.
|
|
157
|
+
|
|
158
|
+
This test specifically catches circular import issues that would occur
|
|
159
|
+
when lintro is installed as a built package (wheel). The issue manifests
|
|
160
|
+
when trying to import bandit parser submodules before the formatters
|
|
161
|
+
have loaded, which triggers a specific circular dependency pattern.
|
|
162
|
+
"""
|
|
163
|
+
# This import sequence triggers the circular import that was fixed
|
|
164
|
+
from lintro.parsers.bandit import bandit_issue, bandit_parser
|
|
165
|
+
|
|
166
|
+
assert bandit_issue is not None
|
|
167
|
+
assert bandit_parser is not None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_parser_lazy_loading() -> None:
|
|
171
|
+
"""Test that parser submodules are lazily loaded, not eagerly imported.
|
|
172
|
+
|
|
173
|
+
Verifies that accessing parser submodules through the parent package
|
|
174
|
+
works via __getattr__ and doesn't cause circular imports.
|
|
175
|
+
"""
|
|
176
|
+
import lintro.parsers
|
|
177
|
+
|
|
178
|
+
# Access submodules via attribute access (triggers __getattr__)
|
|
179
|
+
bandit = lintro.parsers.bandit
|
|
180
|
+
actionlint = lintro.parsers.actionlint
|
|
181
|
+
|
|
182
|
+
assert bandit is not None
|
|
183
|
+
assert actionlint is not None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def test_parser_lazy_loading_attribute_error() -> None:
|
|
187
|
+
"""Test that accessing non-existent parser raises AttributeError.
|
|
188
|
+
|
|
189
|
+
Verifies that the __getattr__ error handling works correctly.
|
|
190
|
+
"""
|
|
191
|
+
import lintro.parsers
|
|
192
|
+
|
|
193
|
+
# Accessing a non-existent submodule should raise AttributeError
|
|
194
|
+
with pytest.raises(AttributeError) as exc_info:
|
|
195
|
+
_ = lintro.parsers.nonexistent_parser
|
|
196
|
+
|
|
197
|
+
assert "nonexistent_parser" in str(exc_info.value)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_parser_dir_function() -> None:
|
|
201
|
+
"""Test that dir() works on parsers module.
|
|
202
|
+
|
|
203
|
+
Verifies that the __dir__ function returns all available submodules.
|
|
204
|
+
"""
|
|
205
|
+
import lintro.parsers
|
|
206
|
+
|
|
207
|
+
# Get the directory listing of the parsers module
|
|
208
|
+
dir_listing = dir(lintro.parsers)
|
|
209
|
+
|
|
210
|
+
# All expected submodules should be in the directory
|
|
211
|
+
expected_modules = {
|
|
212
|
+
"actionlint",
|
|
213
|
+
"bandit",
|
|
214
|
+
"darglint",
|
|
215
|
+
"hadolint",
|
|
216
|
+
"prettier",
|
|
217
|
+
"ruff",
|
|
218
|
+
"yamllint",
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
for module in expected_modules:
|
|
222
|
+
assert module in dir_listing
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"""Parser modules for Lintro tools."""
|
|
2
|
-
|
|
3
|
-
from . import (
|
|
4
|
-
actionlint,
|
|
5
|
-
bandit,
|
|
6
|
-
darglint,
|
|
7
|
-
hadolint,
|
|
8
|
-
prettier,
|
|
9
|
-
ruff,
|
|
10
|
-
yamllint,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
__all__ = [
|
|
14
|
-
"actionlint",
|
|
15
|
-
"bandit",
|
|
16
|
-
"darglint",
|
|
17
|
-
"hadolint",
|
|
18
|
-
"prettier",
|
|
19
|
-
"ruff",
|
|
20
|
-
"yamllint",
|
|
21
|
-
]
|
|
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
|
|
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
|
|
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
|
|
File without changes
|