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.
Files changed (116) hide show
  1. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/CICD.yml +0 -1
  2. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/CICD_impl.yml +1 -24
  3. repoauditor-0.2.24/.github/workflows/EndToEnd.yml +48 -0
  4. {repoauditor-0.2.22 → repoauditor-0.2.24}/PKG-INFO +1 -1
  5. {repoauditor-0.2.22 → repoauditor-0.2.24}/pyproject.toml +3 -2
  6. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/CommandLineProcessor.py +128 -63
  7. repoauditor-0.2.24/src/RepoAuditor/Display.py +165 -0
  8. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/EntryPoint.py +10 -10
  9. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/ExecuteModules.py +73 -177
  10. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +1 -1
  11. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +1 -1
  12. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/Protected.py +1 -1
  13. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +1 -1
  14. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Description.py +1 -1
  15. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardEnableRequirementImpl.py +1 -1
  16. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Private.py +1 -1
  17. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/__init__.py +1 -1
  18. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/ExecuteModules_UnitTest.py +1 -0
  19. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHub_EndToEndTest.py +3 -4
  20. {repoauditor-0.2.22 → repoauditor-0.2.24}/.copier-answers.yml +0 -0
  21. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/CODEOWNERS +0 -0
  22. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  23. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  25. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  26. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/actions/release_impl/action.yml +0 -0
  27. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/pull_request_template.md +0 -0
  28. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/release_sources.yaml +0 -0
  29. {repoauditor-0.2.22 → repoauditor-0.2.24}/.github/workflows/codeql.yml +0 -0
  30. {repoauditor-0.2.22 → repoauditor-0.2.24}/.gitignore +0 -0
  31. {repoauditor-0.2.22 → repoauditor-0.2.24}/.pre-commit-config.yaml +0 -0
  32. {repoauditor-0.2.22 → repoauditor-0.2.24}/.python-version +0 -0
  33. {repoauditor-0.2.22 → repoauditor-0.2.24}/CODE_OF_CONDUCT.md +0 -0
  34. {repoauditor-0.2.22 → repoauditor-0.2.24}/CONTRIBUTING.md +0 -0
  35. {repoauditor-0.2.22 → repoauditor-0.2.24}/DEVELOPMENT.md +0 -0
  36. {repoauditor-0.2.22 → repoauditor-0.2.24}/GOVERNANCE.md +0 -0
  37. {repoauditor-0.2.22 → repoauditor-0.2.24}/LICENSE +0 -0
  38. {repoauditor-0.2.22 → repoauditor-0.2.24}/MAINTAINERS.md +0 -0
  39. {repoauditor-0.2.22 → repoauditor-0.2.24}/README.md +0 -0
  40. {repoauditor-0.2.22 → repoauditor-0.2.24}/SECURITY.md +0 -0
  41. {repoauditor-0.2.22 → repoauditor-0.2.24}/minisign_key.pub +0 -0
  42. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/AutoGitSemVer.yaml +0 -0
  43. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +0 -0
  44. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Impl/__init__.py +0 -0
  45. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Module.py +0 -0
  46. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugin.py +0 -0
  47. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +0 -0
  48. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
  49. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowForcePushes.py +0 -0
  50. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
  51. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +0 -0
  52. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
  53. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
  54. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
  55. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
  56. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
  57. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
  58. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
  59. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
  60. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
  61. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
  62. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
  63. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
  64. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
  65. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/__init__.py +0 -0
  66. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
  67. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
  68. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
  69. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/Module.py +0 -0
  70. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
  71. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/AutoMerge.py +0 -0
  72. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DefaultBranch.py +0 -0
  73. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DeleteHeadBranches.py +0 -0
  74. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DependabotSecurityUpdates.py +0 -0
  75. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardValueRequirementImpl.py +0 -0
  76. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/__init__.py +0 -0
  77. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/License.py +0 -0
  78. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommit.py +0 -0
  79. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommitMessage.py +0 -0
  80. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/RebaseMergeCommit.py +0 -0
  81. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanning.py +0 -0
  82. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanningPushProtection.py +0 -0
  83. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashCommitMerge.py +0 -0
  84. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashMergeCommitMessage.py +0 -0
  85. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
  86. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportDiscussions.py +0 -0
  87. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportIssues.py +0 -0
  88. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportProjects.py +0 -0
  89. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportWikis.py +0 -0
  90. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/TemplateRepository.py +0 -0
  91. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/WebCommitSignoff.py +0 -0
  92. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/__init__.py +0 -0
  93. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
  94. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubBase/Module.py +0 -0
  95. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubBase/__init__.py +0 -0
  96. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/CustomizationQuery.py +0 -0
  97. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/Module.py +0 -0
  98. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomization/__init__.py +0 -0
  99. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubCustomizationPlugin.py +0 -0
  100. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
  101. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Plugins/__init__.py +0 -0
  102. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Query.py +0 -0
  103. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/Requirement.py +0 -0
  104. {repoauditor-0.2.22 → repoauditor-0.2.24}/src/RepoAuditor/py.typed +0 -0
  105. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/CommandLineProcessor_UnitTest.py +0 -0
  106. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/EntryPoint_UnitTest.py +0 -0
  107. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Module_UnitTest.py +0 -0
  108. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugin_UnitTest.py +0 -0
  109. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHubCustomization_UnitTest.py +0 -0
  110. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/GitHubModule_UnitTest.py +0 -0
  111. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +0 -0
  112. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Plugins/utilities.py +0 -0
  113. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Query_UnitTest.py +0 -0
  114. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/Requirement_UnitTest.py +0 -0
  115. {repoauditor-0.2.22 → repoauditor-0.2.24}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
  116. {repoauditor-0.2.22 → repoauditor-0.2.24}/uv.lock +0 -0
@@ -36,4 +36,3 @@ jobs:
36
36
  MINISIGN_PRIVATE_KEY: ${{ secrets.MINISIGN_PRIVATE_KEY }}
37
37
  PYPI_PUBLISH_TOKEN: ${{ secrets.PYPI_PUBLISH_TOKEN }}
38
38
  COVERAGE_BADGE_GIST_TOKEN: ${{ secrets.COVERAGE_BADGE_GIST_TOKEN }}
39
- TESTING_GITHUB_PAT: ${{ secrets.TESTING_GITHUB_PAT }}
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RepoAuditor
3
- Version: 0.2.22
3
+ Version: 0.2.24
4
4
  Summary: Add your description here
5
5
  Project-URL: Homepage, https://github.com/gt-sse-center/RepoAuditor
6
6
  Project-URL: Documentation, https://github.com/gt-sse-center/RepoAuditor
@@ -83,7 +83,7 @@ select = [
83
83
  "ASYNC",
84
84
  "S",
85
85
  "BLE",
86
- # "FBT", # 44
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
- # "C90", # 3
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
- includes: list[str],
60
- excludes: list[str],
61
- warnings_as_error_module_names: set[str],
62
- ignore_warnings_module_names: set[str],
63
- *,
64
- all_warnings_as_error: bool = False,
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
- prev_module = module_map.get(module.name, None)
79
- if prev_module is not None:
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
- del modules
62
+ return module_map
86
63
 
87
- # Process includes
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
- del includes
93
+ return included_modules, included_requirements
107
94
 
108
- for module_name, module in list(module_map.items()):
109
- if module.requires_explicit_include and module_name not in included_modules:
110
- module_map.pop(module_name)
111
- continue
112
-
113
- del included_modules
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
- # Process excludes
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
- del excludes
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
- if module.GetNumRequirements() == 0:
143
- module_map.pop(module_name)
144
-
145
- del included_requirements
146
- del excluded_requirements
147
-
148
- if all_warnings_as_error:
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
- # Create the type definitions
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
- # Process the dynamic info
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.ExecuteModules import DisplayResults
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",