RepoAuditor 0.2.22__tar.gz → 0.2.24__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.
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/CICD.yml +0 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/CICD_impl.yml +1 -24
- repoauditor-0.2.24/.github/workflows/EndToEnd.yml +48 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/PKG-INFO +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/pyproject.toml +3 -2
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/CommandLineProcessor.py +128 -63
- repoauditor-0.2.24/src/RepoAuditor/Display.py +165 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/EntryPoint.py +10 -10
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/ExecuteModules.py +73 -177
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/Protected.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Description.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardEnableRequirementImpl.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Private.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/__init__.py +1 -1
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/ExecuteModules_UnitTest.py +1 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHub_EndToEndTest.py +3 -4
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.copier-answers.yml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/CODEOWNERS +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/custom.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/actions/release_impl/action.yml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/pull_request_template.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/release_sources.yaml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/codeql.yml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.gitignore +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.pre-commit-config.yaml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/.python-version +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/CODE_OF_CONDUCT.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/CONTRIBUTING.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/DEVELOPMENT.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/GOVERNANCE.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/LICENSE +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/MAINTAINERS.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/README.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/SECURITY.md +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/minisign_key.pub +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/AutoGitSemVer.yaml +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Impl/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Module.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugin.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowForcePushes.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Module.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/AutoMerge.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DefaultBranch.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DeleteHeadBranches.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DependabotSecurityUpdates.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardValueRequirementImpl.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/License.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommit.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommitMessage.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/RebaseMergeCommit.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanning.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanningPushProtection.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashCommitMerge.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashMergeCommitMessage.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportDiscussions.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportIssues.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportProjects.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportWikis.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/TemplateRepository.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/WebCommitSignoff.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubBase/Module.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubBase/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/CustomizationQuery.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/Module.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomizationPlugin.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/__init__.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Query.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Requirement.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/py.typed +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/CommandLineProcessor_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/EntryPoint_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Module_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugin_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHubCustomization_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHubModule_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/utilities.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Query_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Requirement_UnitTest.py +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
- {repoauditor-0.2.22 → repoauditor-0.2.24}/uv.lock +0 -0
|
@@ -41,10 +41,6 @@ on:
|
|
|
41
41
|
required: false
|
|
42
42
|
description: "Token used to access the Gist used to store coverage badge information. Code coverage information will not be persisted if this value is missing."
|
|
43
43
|
|
|
44
|
-
TESTING_GITHUB_PAT:
|
|
45
|
-
required: true
|
|
46
|
-
description: "GitHub PAT used by tests to access the repository. This value is required."
|
|
47
|
-
|
|
48
44
|
jobs:
|
|
49
45
|
# ----------------------------------------------------------------------
|
|
50
46
|
validate:
|
|
@@ -70,30 +66,11 @@ jobs:
|
|
|
70
66
|
python-version: ${{ matrix.python_version }}
|
|
71
67
|
enable-cache: true
|
|
72
68
|
|
|
73
|
-
# Ensure that the github PAT is available for the tests
|
|
74
|
-
- name: Create github_pat.txt
|
|
75
|
-
run: |
|
|
76
|
-
echo ${{ secrets.TESTING_GITHUB_PAT }} > tests/Plugins/github_pat.txt
|
|
77
|
-
|
|
78
|
-
- name: Environment Variables (!Windows)
|
|
79
|
-
shell: bash
|
|
80
|
-
if: ${{ ! startsWith(matrix.os, 'windows') }}
|
|
81
|
-
run: |
|
|
82
|
-
echo "GITHUB_CI_OPERATING_SYSTEM=${{ matrix.os }}" >> $GITHUB_ENV
|
|
83
|
-
echo "GITHUB_CI_PYTHON_VERSION=${{ matrix.python_version }}" >> $GITHUB_ENV
|
|
84
|
-
|
|
85
|
-
- name: Environment Variables (Windows)
|
|
86
|
-
shell: cmd
|
|
87
|
-
if: ${{ startsWith(matrix.os, 'windows') }}
|
|
88
|
-
run: |
|
|
89
|
-
echo GITHUB_CI_OPERATING_SYSTEM=${{ matrix.os }} >> %GITHUB_ENV%
|
|
90
|
-
echo GITHUB_CI_PYTHON_VERSION=${{ matrix.python_version }} >> %GITHUB_ENV%
|
|
91
|
-
|
|
92
69
|
- name: Run pre-commit scripts
|
|
93
70
|
run: uv run pre-commit run --verbose
|
|
94
71
|
|
|
95
72
|
- name: Validate Tests
|
|
96
|
-
run: uv run pytest
|
|
73
|
+
run: uv run pytest -k 'not EndToEndTest' --cov-fail-under=80.0
|
|
97
74
|
env:
|
|
98
75
|
COVERAGE_FILE: .coverage.${{ matrix.os }}.${{ matrix.python_version }}
|
|
99
76
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: "End To End Tests"
|
|
2
|
+
run-name: EndToEnd ${{ github.run_number }} [${{ github.actor }}] on ${{ github.ref_name }}
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: '0 * * * *' # Once every hour
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
validate:
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
|
|
14
|
+
matrix:
|
|
15
|
+
# Since the system under test here is the GitHub API, it is sufficient to test using only a single OS.
|
|
16
|
+
os: ["ubuntu-latest"]
|
|
17
|
+
# Similar to OS, we only test the lowest and highest supported versions.
|
|
18
|
+
python_version: ["3.10", "3.13"]
|
|
19
|
+
|
|
20
|
+
name: Validate
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Install uv and python
|
|
30
|
+
uses: astral-sh/setup-uv@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python_version }}
|
|
33
|
+
enable-cache: true
|
|
34
|
+
|
|
35
|
+
# Ensure that the github PAT is available for the tests
|
|
36
|
+
# GitHub PAT used by tests to access the repository.
|
|
37
|
+
- name: Create github_pat.txt
|
|
38
|
+
run: |
|
|
39
|
+
echo ${{ secrets.TESTING_GITHUB_PAT }} > tests/Plugins/github_pat.txt
|
|
40
|
+
|
|
41
|
+
- name: Environment Variables
|
|
42
|
+
shell: bash
|
|
43
|
+
run: |
|
|
44
|
+
echo "GITHUB_CI_OPERATING_SYSTEM=${{ matrix.os }}" >> $GITHUB_ENV
|
|
45
|
+
echo "GITHUB_CI_PYTHON_VERSION=${{ matrix.python_version }}" >> $GITHUB_ENV
|
|
46
|
+
|
|
47
|
+
- name: Validate Tests
|
|
48
|
+
run: uv run pytest -k EndToEndTest --no-cov
|
|
@@ -83,7 +83,7 @@ select = [
|
|
|
83
83
|
"ASYNC",
|
|
84
84
|
"S",
|
|
85
85
|
"BLE",
|
|
86
|
-
|
|
86
|
+
"FBT",
|
|
87
87
|
"B",
|
|
88
88
|
"A",
|
|
89
89
|
"COM",
|
|
@@ -119,7 +119,7 @@ select = [
|
|
|
119
119
|
"PTH",
|
|
120
120
|
"FLY",
|
|
121
121
|
"I",
|
|
122
|
-
|
|
122
|
+
"C90",
|
|
123
123
|
"NPY",
|
|
124
124
|
"PD",
|
|
125
125
|
"N",
|
|
@@ -148,6 +148,7 @@ ignore = [
|
|
|
148
148
|
"D107", # Missing docstring in `__init__` method
|
|
149
149
|
"D202", # No blank lines allowed after function docstring
|
|
150
150
|
"E501", # Line too long
|
|
151
|
+
"FBT003", # Boolean positional argument in function call
|
|
151
152
|
"I001", # Import block is un-sorted or un-formatted
|
|
152
153
|
"N802", # Function name `xxx` should be lowercase
|
|
153
154
|
"N999", # Invalid module name
|
|
@@ -36,38 +36,15 @@ class CommandLineProcessor:
|
|
|
36
36
|
], # actual type is dict[str, TyperEx.TypeDefinitionItemType]
|
|
37
37
|
) -> dict[str, Any]: ...
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# | Public Data
|
|
42
|
-
# |
|
|
43
|
-
# ----------------------------------------------------------------------
|
|
44
|
-
module_infos: list[ModuleInfo]
|
|
45
|
-
warnings_as_error_module_names: set[str]
|
|
46
|
-
ignore_warnings_module_names: set[str]
|
|
47
|
-
single_threaded: bool = field(kw_only=True)
|
|
48
|
-
|
|
49
|
-
# ----------------------------------------------------------------------
|
|
50
|
-
# |
|
|
51
|
-
# | Public Methods
|
|
52
|
-
# |
|
|
53
|
-
# ----------------------------------------------------------------------
|
|
54
|
-
@classmethod
|
|
55
|
-
def Create(
|
|
56
|
-
cls,
|
|
57
|
-
get_dynamic_args_func: "CommandLineProcessor.GetDynamicArgsFunc",
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _GetModuleMap(
|
|
58
41
|
modules: list[Module],
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
ignore_all_warnings: bool = False,
|
|
66
|
-
single_threaded: bool = False,
|
|
67
|
-
argument_separator: str = "-",
|
|
68
|
-
) -> "CommandLineProcessor":
|
|
69
|
-
"""Factor method to construct a CommandLineProcessor object."""
|
|
70
|
-
# Convert modules into a lookup map
|
|
42
|
+
argument_separator: str,
|
|
43
|
+
) -> dict[str, Module]:
|
|
44
|
+
"""Convert modules into a lookup map.
|
|
45
|
+
|
|
46
|
+
Returns a dict of module names mapped to the corresponding module.
|
|
47
|
+
"""
|
|
71
48
|
module_map: dict[str, Module] = {}
|
|
72
49
|
|
|
73
50
|
for module in modules:
|
|
@@ -75,16 +52,26 @@ class CommandLineProcessor:
|
|
|
75
52
|
msg = f"The module name '{module.name}' contains '{argument_separator}', which should be used as an argument separator."
|
|
76
53
|
raise ValueError(msg)
|
|
77
54
|
|
|
78
|
-
|
|
79
|
-
if
|
|
55
|
+
prev_added_module = module_map.get(module.name, None)
|
|
56
|
+
if prev_added_module is not None:
|
|
80
57
|
msg = f"The module '{module.name}' has already been defined."
|
|
81
58
|
raise ValueError(msg)
|
|
82
59
|
|
|
83
60
|
module_map[module.name] = module
|
|
84
61
|
|
|
85
|
-
|
|
62
|
+
return module_map
|
|
86
63
|
|
|
87
|
-
|
|
64
|
+
@staticmethod
|
|
65
|
+
def _ProcessIncludes(
|
|
66
|
+
module_map: dict[str, Module],
|
|
67
|
+
includes: list[str],
|
|
68
|
+
argument_separator: str,
|
|
69
|
+
) -> tuple[set[str], dict[str, set[str]]]:
|
|
70
|
+
"""Process the modules and requirements to include.
|
|
71
|
+
|
|
72
|
+
Returns both the set of names of the included modules as well as
|
|
73
|
+
the dictionary of module names mapped to the set of included requirement names.
|
|
74
|
+
"""
|
|
88
75
|
included_modules: set[str] = set()
|
|
89
76
|
included_requirements: dict[str, set[str]] = {}
|
|
90
77
|
|
|
@@ -103,16 +90,19 @@ class CommandLineProcessor:
|
|
|
103
90
|
argument_separator.join(parts[1:])
|
|
104
91
|
)
|
|
105
92
|
|
|
106
|
-
|
|
93
|
+
return included_modules, included_requirements
|
|
107
94
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
95
|
+
@staticmethod
|
|
96
|
+
def _ProcessExcludes(
|
|
97
|
+
module_map: dict[str, Module],
|
|
98
|
+
excludes: list[str],
|
|
99
|
+
argument_separator: str,
|
|
100
|
+
) -> dict[str, set[str]]:
|
|
101
|
+
"""Process the modules and requirements to exclude.
|
|
114
102
|
|
|
115
|
-
|
|
103
|
+
Returns both the set of names of the excluded modules as well as
|
|
104
|
+
the dictionary of module names mapped to the set of excluded requirement names.
|
|
105
|
+
"""
|
|
116
106
|
excluded_requirements: dict[str, set[str]] = {}
|
|
117
107
|
|
|
118
108
|
for exclude in excludes:
|
|
@@ -130,27 +120,20 @@ class CommandLineProcessor:
|
|
|
130
120
|
argument_separator.join(parts[1:])
|
|
131
121
|
)
|
|
132
122
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# Add / Remove the requirements for each module
|
|
136
|
-
for module_name, module in list(module_map.items()):
|
|
137
|
-
module.ProcessRequirements(
|
|
138
|
-
included_requirements.get(module_name, set()),
|
|
139
|
-
excluded_requirements.get(module_name, set()),
|
|
140
|
-
)
|
|
123
|
+
return excluded_requirements
|
|
141
124
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
warnings_as_error_module_names = {module.name for module in module_map.values()}
|
|
150
|
-
if ignore_all_warnings:
|
|
151
|
-
ignore_warnings_module_names = {module.name for module in module_map.values()}
|
|
125
|
+
@staticmethod
|
|
126
|
+
def _ProcessDynamicArguments(
|
|
127
|
+
module_map: dict[str, Module],
|
|
128
|
+
argument_separator: str,
|
|
129
|
+
get_dynamic_args_func: "CommandLineProcessor.GetDynamicArgsFunc",
|
|
130
|
+
) -> dict[str, dict[str, Any]]:
|
|
131
|
+
"""Process the passed in dynamic arguments.
|
|
152
132
|
|
|
153
|
-
|
|
133
|
+
Returns a dictionary of module names to a corresponding dictionary
|
|
134
|
+
of argument names to values.
|
|
135
|
+
"""
|
|
136
|
+
# First we create the type definitions
|
|
154
137
|
dynamic_arg_definitions: dict[str, Any] = {}
|
|
155
138
|
|
|
156
139
|
for module in module_map.values():
|
|
@@ -166,7 +149,7 @@ class CommandLineProcessor:
|
|
|
166
149
|
f"{module.name}{argument_separator}{requirement.name}{argument_separator}{key}"
|
|
167
150
|
] = value
|
|
168
151
|
|
|
169
|
-
#
|
|
152
|
+
# Now we process the definitions to get the dynamic arguments
|
|
170
153
|
dynamic_args: dict[str, dict[str, Any]] = {}
|
|
171
154
|
|
|
172
155
|
for key, value in get_dynamic_args_func(dynamic_arg_definitions).items():
|
|
@@ -185,6 +168,88 @@ class CommandLineProcessor:
|
|
|
185
168
|
{},
|
|
186
169
|
)[argument_separator.join(parts[2:])] = value
|
|
187
170
|
|
|
171
|
+
return dynamic_args
|
|
172
|
+
|
|
173
|
+
# ----------------------------------------------------------------------
|
|
174
|
+
# |
|
|
175
|
+
# | Public Data
|
|
176
|
+
# |
|
|
177
|
+
# ----------------------------------------------------------------------
|
|
178
|
+
module_infos: list[ModuleInfo]
|
|
179
|
+
warnings_as_error_module_names: set[str]
|
|
180
|
+
ignore_warnings_module_names: set[str]
|
|
181
|
+
single_threaded: bool = field(kw_only=True)
|
|
182
|
+
|
|
183
|
+
# ----------------------------------------------------------------------
|
|
184
|
+
# |
|
|
185
|
+
# | Public Methods
|
|
186
|
+
# |
|
|
187
|
+
# ----------------------------------------------------------------------
|
|
188
|
+
@classmethod
|
|
189
|
+
def Create(
|
|
190
|
+
cls,
|
|
191
|
+
get_dynamic_args_func: "CommandLineProcessor.GetDynamicArgsFunc",
|
|
192
|
+
modules: list[Module],
|
|
193
|
+
includes: list[str],
|
|
194
|
+
excludes: list[str],
|
|
195
|
+
warnings_as_error_module_names: set[str],
|
|
196
|
+
ignore_warnings_module_names: set[str],
|
|
197
|
+
*,
|
|
198
|
+
all_warnings_as_error: bool = False,
|
|
199
|
+
ignore_all_warnings: bool = False,
|
|
200
|
+
single_threaded: bool = False,
|
|
201
|
+
argument_separator: str = "-",
|
|
202
|
+
) -> "CommandLineProcessor":
|
|
203
|
+
"""Factor method to construct a CommandLineProcessor object."""
|
|
204
|
+
# Convert modules into a lookup map
|
|
205
|
+
module_map: dict[str, Module] = cls._GetModuleMap(modules, argument_separator)
|
|
206
|
+
|
|
207
|
+
del modules
|
|
208
|
+
|
|
209
|
+
# Process includes
|
|
210
|
+
included_modules, included_requirements = cls._ProcessIncludes(
|
|
211
|
+
module_map, includes, argument_separator
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
del includes
|
|
215
|
+
|
|
216
|
+
for module_name, module in list(module_map.items()):
|
|
217
|
+
if module.requires_explicit_include and module_name not in included_modules:
|
|
218
|
+
module_map.pop(module_name)
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
del included_modules
|
|
222
|
+
|
|
223
|
+
# Process excludes
|
|
224
|
+
excluded_requirements: dict[str, set[str]] = cls._ProcessExcludes(
|
|
225
|
+
module_map, excludes, argument_separator
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
del excludes
|
|
229
|
+
|
|
230
|
+
# Add / Remove the requirements for each module
|
|
231
|
+
for module_name, module in list(module_map.items()):
|
|
232
|
+
module.ProcessRequirements(
|
|
233
|
+
included_requirements.get(module_name, set()),
|
|
234
|
+
excluded_requirements.get(module_name, set()),
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
if module.GetNumRequirements() == 0:
|
|
238
|
+
module_map.pop(module_name)
|
|
239
|
+
|
|
240
|
+
del included_requirements
|
|
241
|
+
del excluded_requirements
|
|
242
|
+
|
|
243
|
+
if all_warnings_as_error:
|
|
244
|
+
warnings_as_error_module_names = {module.name for module in module_map.values()}
|
|
245
|
+
if ignore_all_warnings:
|
|
246
|
+
ignore_warnings_module_names = {module.name for module in module_map.values()}
|
|
247
|
+
|
|
248
|
+
# Process the dynamic info
|
|
249
|
+
dynamic_args: dict[str, dict[str, Any]] = cls._ProcessDynamicArguments(
|
|
250
|
+
module_map, argument_separator, get_dynamic_args_func
|
|
251
|
+
)
|
|
252
|
+
|
|
188
253
|
module_infos: list[ModuleInfo] = []
|
|
189
254
|
|
|
190
255
|
for module_name, module in module_map.items():
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# -------------------------------------------------------------------------------
|
|
2
|
+
# |
|
|
3
|
+
# | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech
|
|
4
|
+
# | Distributed under the MIT License.
|
|
5
|
+
# |
|
|
6
|
+
# -------------------------------------------------------------------------------
|
|
7
|
+
"""Contains functionality to display the results of executing modules."""
|
|
8
|
+
|
|
9
|
+
import textwrap
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
from dbrownell_Common.Streams.DoneManager import DoneManager # type: ignore[import-untyped]
|
|
13
|
+
from dbrownell_Common import TextwrapEx # type: ignore[import-untyped]
|
|
14
|
+
from rich import print as rich_print
|
|
15
|
+
from rich.console import Group
|
|
16
|
+
from rich.panel import Panel
|
|
17
|
+
|
|
18
|
+
from .Module import EvaluateResult, Module
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def GetInternalPanelContent(
|
|
22
|
+
dm: DoneManager,
|
|
23
|
+
results: list[Module.EvaluateInfo],
|
|
24
|
+
display_resolution: bool, # noqa: FBT001
|
|
25
|
+
display_rationale: bool, # noqa: FBT001
|
|
26
|
+
num_success: int,
|
|
27
|
+
num_warning: int,
|
|
28
|
+
num_error: int,
|
|
29
|
+
num_does_not_apply: int,
|
|
30
|
+
num_requirements: int,
|
|
31
|
+
) -> list[Panel | str]:
|
|
32
|
+
"""Get the content for each result to be displayed inside the internal panel."""
|
|
33
|
+
internal_content: list[Panel | str] = []
|
|
34
|
+
|
|
35
|
+
module = results[0].module
|
|
36
|
+
|
|
37
|
+
if module.description:
|
|
38
|
+
internal_content.append(f"{module.description.strip()}\n")
|
|
39
|
+
|
|
40
|
+
internal_content.append(
|
|
41
|
+
textwrap.dedent(
|
|
42
|
+
f"""\
|
|
43
|
+
Successful: {num_success} ({(num_success / num_requirements):.02%})
|
|
44
|
+
Warnings: {num_warning} ({(num_warning / num_requirements):.02%})
|
|
45
|
+
Errors: {num_error} ({(num_error / num_requirements):.02%})
|
|
46
|
+
Skipped: {num_does_not_apply} ({(num_does_not_apply / num_requirements):.02%})
|
|
47
|
+
""",
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
for result in results:
|
|
52
|
+
if not dm.is_verbose and result.result in [
|
|
53
|
+
EvaluateResult.Success,
|
|
54
|
+
EvaluateResult.DoesNotApply,
|
|
55
|
+
]:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
if result.result == EvaluateResult.Success:
|
|
59
|
+
border_color = "green"
|
|
60
|
+
elif result.result == EvaluateResult.Warning:
|
|
61
|
+
border_color = "yellow"
|
|
62
|
+
elif result.result == EvaluateResult.Error:
|
|
63
|
+
border_color = "red"
|
|
64
|
+
elif result.result == EvaluateResult.DoesNotApply:
|
|
65
|
+
border_color = ""
|
|
66
|
+
else:
|
|
67
|
+
raise RuntimeError(result.result) # pragma: no cover
|
|
68
|
+
|
|
69
|
+
content: list[str] = []
|
|
70
|
+
|
|
71
|
+
if result.requirement.description:
|
|
72
|
+
content.append(f"{result.requirement.description.strip()}\n")
|
|
73
|
+
|
|
74
|
+
if result.context:
|
|
75
|
+
content.append(f"{result.result.name.upper()}: {result.context.strip()}\n")
|
|
76
|
+
|
|
77
|
+
if display_resolution and result.resolution:
|
|
78
|
+
content.append(
|
|
79
|
+
textwrap.dedent(
|
|
80
|
+
"""\
|
|
81
|
+
Resolution
|
|
82
|
+
----------
|
|
83
|
+
{}
|
|
84
|
+
""",
|
|
85
|
+
).format(TextwrapEx.Indent(result.resolution.strip(), 2, skip_first_line=True)),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if display_rationale and result.rationale:
|
|
89
|
+
content.append(
|
|
90
|
+
textwrap.dedent(
|
|
91
|
+
"""\
|
|
92
|
+
Rationale
|
|
93
|
+
---------
|
|
94
|
+
{}
|
|
95
|
+
""",
|
|
96
|
+
).format(TextwrapEx.Indent(result.rationale.strip(), 2, skip_first_line=True)),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
internal_content.append(
|
|
100
|
+
Panel(
|
|
101
|
+
Group(*content),
|
|
102
|
+
title=f"[{result.result.name}] {result.requirement.name}",
|
|
103
|
+
title_align="left",
|
|
104
|
+
border_style=border_color,
|
|
105
|
+
padding=(1, 1, 0, 1) if content else 0,
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return internal_content
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# ----------------------------------------------------------------------
|
|
113
|
+
def DisplayResults(
|
|
114
|
+
dm: DoneManager,
|
|
115
|
+
all_results: list[list[Module.EvaluateInfo]],
|
|
116
|
+
*,
|
|
117
|
+
display_resolution: bool,
|
|
118
|
+
display_rationale: bool,
|
|
119
|
+
panel_width: Optional[int] = None,
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Display the results of executing the modules."""
|
|
122
|
+
for results in all_results:
|
|
123
|
+
assert results
|
|
124
|
+
module = results[0].module
|
|
125
|
+
|
|
126
|
+
num_success = 0
|
|
127
|
+
num_warning = 0
|
|
128
|
+
num_error = 0
|
|
129
|
+
num_does_not_apply = 0
|
|
130
|
+
|
|
131
|
+
for result in results:
|
|
132
|
+
if result.result == EvaluateResult.Success:
|
|
133
|
+
num_success += 1
|
|
134
|
+
elif result.result == EvaluateResult.Warning:
|
|
135
|
+
num_warning += 1
|
|
136
|
+
elif result.result == EvaluateResult.Error:
|
|
137
|
+
num_error += 1
|
|
138
|
+
elif result.result == EvaluateResult.DoesNotApply:
|
|
139
|
+
num_does_not_apply += 1
|
|
140
|
+
else:
|
|
141
|
+
raise RuntimeError(result.result) # pragma: no cover
|
|
142
|
+
|
|
143
|
+
num_requirements = module.GetNumRequirements()
|
|
144
|
+
assert num_requirements
|
|
145
|
+
|
|
146
|
+
internal_content: list[Panel | str] = GetInternalPanelContent(
|
|
147
|
+
dm,
|
|
148
|
+
results,
|
|
149
|
+
display_resolution,
|
|
150
|
+
display_rationale,
|
|
151
|
+
num_success=num_success,
|
|
152
|
+
num_warning=num_warning,
|
|
153
|
+
num_error=num_error,
|
|
154
|
+
num_does_not_apply=num_does_not_apply,
|
|
155
|
+
num_requirements=num_requirements,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
rich_print(
|
|
159
|
+
Panel(
|
|
160
|
+
Group(*internal_content),
|
|
161
|
+
padding=1 if internal_content else 0,
|
|
162
|
+
title=results[0].module.name,
|
|
163
|
+
width=panel_width,
|
|
164
|
+
),
|
|
165
|
+
)
|
|
@@ -23,7 +23,7 @@ from typer.core import TyperGroup # type: ignore [import-untyped]
|
|
|
23
23
|
|
|
24
24
|
from RepoAuditor import APP_NAME, __version__
|
|
25
25
|
from RepoAuditor.CommandLineProcessor import CommandLineProcessor, Module
|
|
26
|
-
from RepoAuditor.
|
|
26
|
+
from RepoAuditor.Display import DisplayResults
|
|
27
27
|
from RepoAuditor import Plugin
|
|
28
28
|
|
|
29
29
|
|
|
@@ -168,7 +168,7 @@ def _HelpEpilog() -> str:
|
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
# ----------------------------------------------------------------------
|
|
171
|
-
def _VersionCallback(value: bool) -> None:
|
|
171
|
+
def _VersionCallback(value: bool) -> None: # noqa: FBT001
|
|
172
172
|
if value:
|
|
173
173
|
sys.stdout.write(f"RepoAuditor v{__version__}\n")
|
|
174
174
|
raise typer.Exit()
|
|
@@ -184,7 +184,7 @@ def _VersionCallback(value: bool) -> None:
|
|
|
184
184
|
)
|
|
185
185
|
def EntryPoint(
|
|
186
186
|
ctx: typer.Context,
|
|
187
|
-
version: Annotated[ # noqa: ARG001
|
|
187
|
+
version: Annotated[ # noqa: ARG001, FBT002
|
|
188
188
|
bool,
|
|
189
189
|
typer.Option(
|
|
190
190
|
"--version",
|
|
@@ -221,38 +221,38 @@ def EntryPoint(
|
|
|
221
221
|
help="Name of a module whose warnings should be ignored. This value can be provided multiple times.",
|
|
222
222
|
),
|
|
223
223
|
] = None,
|
|
224
|
-
all_warnings_as_error: Annotated[
|
|
224
|
+
all_warnings_as_error: Annotated[ # noqa: FBT002
|
|
225
225
|
bool, typer.Option("--all-warnings-as-error", help="Treat all warnings as errors.")
|
|
226
226
|
] = False,
|
|
227
|
-
ignore_all_warnings: Annotated[
|
|
227
|
+
ignore_all_warnings: Annotated[ # noqa: FBT002
|
|
228
228
|
bool, typer.Option("--ignore-all-warnings", help="Ignore all warnings.")
|
|
229
229
|
] = False,
|
|
230
|
-
single_threaded: Annotated[
|
|
230
|
+
single_threaded: Annotated[ # noqa: FBT002
|
|
231
231
|
bool,
|
|
232
232
|
typer.Option("--single-threaded", help="Do not use multiple threads when evaluating requirements."),
|
|
233
233
|
] = False,
|
|
234
|
-
no_resolution: Annotated[
|
|
234
|
+
no_resolution: Annotated[ # noqa: FBT002
|
|
235
235
|
bool,
|
|
236
236
|
typer.Option(
|
|
237
237
|
"--no-resolution",
|
|
238
238
|
help="Do not display resolution information for requirements that are not successful.",
|
|
239
239
|
),
|
|
240
240
|
] = False,
|
|
241
|
-
no_rationale: Annotated[
|
|
241
|
+
no_rationale: Annotated[ # noqa: FBT002
|
|
242
242
|
bool,
|
|
243
243
|
typer.Option(
|
|
244
244
|
"--no-rationale",
|
|
245
245
|
help="Do not display rationale information for requirements that are not successful.",
|
|
246
246
|
),
|
|
247
247
|
] = False,
|
|
248
|
-
verbose: Annotated[
|
|
248
|
+
verbose: Annotated[ # noqa: FBT002
|
|
249
249
|
bool,
|
|
250
250
|
typer.Option(
|
|
251
251
|
"--verbose",
|
|
252
252
|
help="Write verbose information to the terminal.",
|
|
253
253
|
),
|
|
254
254
|
] = False,
|
|
255
|
-
debug: Annotated[
|
|
255
|
+
debug: Annotated[ # noqa: FBT002
|
|
256
256
|
bool,
|
|
257
257
|
typer.Option(
|
|
258
258
|
"--debug",
|