RepoAuditor 0.2.28__tar.gz → 0.2.30__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 (140) hide show
  1. {repoauditor-0.2.28 → repoauditor-0.2.30}/PKG-INFO +1 -1
  2. {repoauditor-0.2.28 → repoauditor-0.2.30}/pyproject.toml +1 -1
  3. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/CommandLineProcessor.py +4 -2
  4. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/EntryPoint.py +1 -1
  5. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Impl/ParallelSequentialProcessor.py +2 -2
  6. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Module.py +3 -0
  7. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionQuery.py +2 -1
  8. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/Impl/EnableRequirementImpl.py +1 -1
  9. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardEnableRequirementImpl.py +1 -1
  10. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubBase/Module.py +2 -1
  11. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/CustomizationQuery.py +17 -5
  12. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Impl/ExistsRequirementImpl.py +14 -18
  13. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Module.py +0 -8
  14. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/CodeOwners.py +0 -5
  15. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/Contributing.py +0 -5
  16. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/IssueTemplates.py +0 -4
  17. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/PullRequestTemplates.py +0 -6
  18. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/SecurityPolicy.py +0 -5
  19. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Impl/EnableRulesetRequirementImpl.py +1 -1
  20. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Query.py +8 -0
  21. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/__init__.py +1 -1
  22. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHubCustomization_EndToEndTest.py +72 -5
  23. repoauditor-0.2.30/tests/Plugins/__snapshots__/GitHubCustomization_EndToEndTest.ambr +403 -0
  24. repoauditor-0.2.28/tests/Plugins/__snapshots__/GitHubCustomization_EndToEndTest.ambr +0 -146
  25. {repoauditor-0.2.28 → repoauditor-0.2.30}/.copier-answers.yml +0 -0
  26. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/CODEOWNERS +0 -0
  27. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  28. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  29. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/ISSUE_TEMPLATE/custom.md +0 -0
  30. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  31. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/actions/release_impl/action.yml +0 -0
  32. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/pull_request_template.md +0 -0
  33. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/release_sources.yaml +0 -0
  34. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/workflows/CICD.yml +0 -0
  35. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/workflows/CICD_impl.yml +0 -0
  36. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/workflows/EndToEnd.yml +0 -0
  37. {repoauditor-0.2.28 → repoauditor-0.2.30}/.github/workflows/codeql.yml +0 -0
  38. {repoauditor-0.2.28 → repoauditor-0.2.30}/.gitignore +0 -0
  39. {repoauditor-0.2.28 → repoauditor-0.2.30}/.pre-commit-config.yaml +0 -0
  40. {repoauditor-0.2.28 → repoauditor-0.2.30}/.python-version +0 -0
  41. {repoauditor-0.2.28 → repoauditor-0.2.30}/CODE_OF_CONDUCT.md +0 -0
  42. {repoauditor-0.2.28 → repoauditor-0.2.30}/CONTRIBUTING.md +0 -0
  43. {repoauditor-0.2.28 → repoauditor-0.2.30}/DEVELOPMENT.md +0 -0
  44. {repoauditor-0.2.28 → repoauditor-0.2.30}/GOVERNANCE.md +0 -0
  45. {repoauditor-0.2.28 → repoauditor-0.2.30}/LICENSE +0 -0
  46. {repoauditor-0.2.28 → repoauditor-0.2.30}/MAINTAINERS.md +0 -0
  47. {repoauditor-0.2.28 → repoauditor-0.2.30}/README.md +0 -0
  48. {repoauditor-0.2.28 → repoauditor-0.2.30}/SECURITY.md +0 -0
  49. {repoauditor-0.2.28 → repoauditor-0.2.30}/minisign_key.pub +0 -0
  50. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/AutoGitSemVer.yaml +0 -0
  51. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Display.py +0 -0
  52. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/ExecuteModules.py +0 -0
  53. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Impl/__init__.py +0 -0
  54. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugin.py +0 -0
  55. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowDeletions.py +0 -0
  56. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/AllowForcePushes.py +0 -0
  57. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DismissStalePullRequestApprovals.py +0 -0
  58. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/DoNotAllowBypassSettings.py +0 -0
  59. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/EnsureStatusChecks.py +0 -0
  60. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicEnableRequirementImpl.py +0 -0
  61. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/ClassicValueRequirementImpl.py +0 -0
  62. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/Impl/__init__.py +0 -0
  63. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovalMostRecentPush.py +0 -0
  64. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireApprovals.py +0 -0
  65. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireCodeOwnerReview.py +0 -0
  66. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireConversationResolution.py +0 -0
  67. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireLinearHistory.py +0 -0
  68. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequirePullRequests.py +0 -0
  69. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireSignedCommits.py +0 -0
  70. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireStatusChecksToPass.py +0 -0
  71. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/RequireUpToDateBranches.py +0 -0
  72. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/ClassicBranchProtectionRequirements/__init__.py +0 -0
  73. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQuery.py +0 -0
  74. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/Protected.py +0 -0
  75. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/DefaultBranchQueryRequirements/__init__.py +0 -0
  76. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/Impl/Common.py +0 -0
  77. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/Impl/ValueRequirementImpl.py +0 -0
  78. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/Impl/__init__.py +0 -0
  79. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/Module.py +0 -0
  80. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQuery.py +0 -0
  81. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/AutoMerge.py +0 -0
  82. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DefaultBranch.py +0 -0
  83. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DeleteHeadBranches.py +0 -0
  84. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/DependabotSecurityUpdates.py +0 -0
  85. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Description.py +0 -0
  86. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/StandardValueRequirementImpl.py +0 -0
  87. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Impl/__init__.py +0 -0
  88. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/License.py +0 -0
  89. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommit.py +0 -0
  90. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/MergeCommitMessage.py +0 -0
  91. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/Private.py +0 -0
  92. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/RebaseMergeCommit.py +0 -0
  93. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanning.py +0 -0
  94. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SecretScanningPushProtection.py +0 -0
  95. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashCommitMerge.py +0 -0
  96. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SquashMergeCommitMessage.py +0 -0
  97. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SuggestUpdatingPullRequestBranches.py +0 -0
  98. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportDiscussions.py +0 -0
  99. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportIssues.py +0 -0
  100. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportProjects.py +0 -0
  101. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/SupportWikis.py +0 -0
  102. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/TemplateRepository.py +0 -0
  103. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/WebCommitSignoff.py +0 -0
  104. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/StandardQueryRequirements/__init__.py +0 -0
  105. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHub/__init__.py +0 -0
  106. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubBase/__init__.py +0 -0
  107. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Impl/__init__.py +0 -0
  108. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/Requirements/__init__.py +0 -0
  109. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomization/__init__.py +0 -0
  110. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubCustomizationPlugin.py +0 -0
  111. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubPlugin.py +0 -0
  112. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Impl/__init__.py +0 -0
  113. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Module.py +0 -0
  114. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequirePullRequests.py +0 -0
  115. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequireSignedCommits.py +0 -0
  116. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/RequireStatusChecks.py +0 -0
  117. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/Requirements/__init__.py +0 -0
  118. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/RulesetQuery.py +0 -0
  119. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesets/__init__.py +0 -0
  120. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/GitHubRulesetsPlugin.py +0 -0
  121. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Plugins/__init__.py +0 -0
  122. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/Requirement.py +0 -0
  123. {repoauditor-0.2.28 → repoauditor-0.2.30}/src/RepoAuditor/py.typed +0 -0
  124. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/CommandLineProcessor_UnitTest.py +0 -0
  125. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/EntryPoint_UnitTest.py +0 -0
  126. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/ExecuteModules_UnitTest.py +0 -0
  127. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Module_UnitTest.py +0 -0
  128. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugin_UnitTest.py +0 -0
  129. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHubCustomization_UnitTest.py +0 -0
  130. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHubModule_UnitTest.py +0 -0
  131. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHubRuleset_EndToEndTest.py +0 -0
  132. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHubRuleset_UnitTest.py +0 -0
  133. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/GitHub_EndToEndTest.py +0 -0
  134. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/__snapshots__/GitHubRuleset_EndToEndTest.ambr +0 -0
  135. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/__snapshots__/GitHub_EndToEndTest.ambr +0 -0
  136. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Plugins/utilities.py +0 -0
  137. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Query_UnitTest.py +0 -0
  138. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/Requirement_UnitTest.py +0 -0
  139. {repoauditor-0.2.28 → repoauditor-0.2.30}/tests/__snapshots__/ExecuteModules_UnitTest.ambr +0 -0
  140. {repoauditor-0.2.28 → repoauditor-0.2.30}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RepoAuditor
3
- Version: 0.2.28
3
+ Version: 0.2.30
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
@@ -131,7 +131,7 @@ select = [
131
131
  "D",
132
132
  "F",
133
133
  "PGH",
134
- # "PL", # 11
134
+ "PL",
135
135
  "UP",
136
136
  "FURB",
137
137
  "RUF",
@@ -152,15 +152,17 @@ class CommandLineProcessor:
152
152
  # Now we process the definitions to get the dynamic arguments
153
153
  dynamic_args: dict[str, dict[str, Any]] = {}
154
154
 
155
+ num_acceptable_dynamic_args_parts = 2
156
+
155
157
  for key, value in get_dynamic_args_func(dynamic_arg_definitions).items():
156
158
  parts = key.split(argument_separator)
157
- assert len(parts) >= 2
159
+ assert len(parts) >= num_acceptable_dynamic_args_parts
158
160
 
159
161
  if parts[0] not in module_map:
160
162
  msg = f"'{parts[0]}' is not a recognized module name."
161
163
  raise ValueError(msg)
162
164
 
163
- if len(parts) == 2:
165
+ if len(parts) == num_acceptable_dynamic_args_parts:
164
166
  dynamic_args.setdefault(parts[0], {})[parts[1]] = value
165
167
  else:
166
168
  dynamic_args.setdefault(parts[0], {}).setdefault(None, {}).setdefault( # type: ignore[call-overload]
@@ -182,7 +182,7 @@ def _VersionCallback(value: bool) -> None: # noqa: FBT001
182
182
  epilog=_HelpEpilog(),
183
183
  no_args_is_help=False,
184
184
  )
185
- def EntryPoint(
185
+ def EntryPoint( # noqa: PLR0913
186
186
  ctx: typer.Context,
187
187
  version: Annotated[ # noqa: ARG001, FBT002
188
188
  bool,
@@ -37,9 +37,9 @@ def ParallelSequentialProcessor(
37
37
  ) -> list[OutputType]:
38
38
  """Process a list of items in parallel and/or sequentially."""
39
39
  if dm is None:
40
- with DoneManager.Create(StreamDecorator(None), "", line_prefix="") as dm:
40
+ with DoneManager.Create(StreamDecorator(None), "", line_prefix="") as _dm:
41
41
  return _Impl(
42
- dm,
42
+ _dm,
43
43
  items,
44
44
  calculate_result_func,
45
45
  max_num_threads,
@@ -182,6 +182,9 @@ class Module(ABC):
182
182
  if evaluate_info.result == EvaluateResult.Warning:
183
183
  return_code = 1
184
184
 
185
+ # Cleanup any resources created during the query
186
+ query.Cleanup(query_data)
187
+
185
188
  return (
186
189
  return_code,
187
190
  [
@@ -61,6 +61,7 @@ RESPONSE:
61
61
 
62
62
  from typing import Any, Optional
63
63
 
64
+ import requests
64
65
  from dbrownell_Common.Types import override # type: ignore[import-untyped]
65
66
 
66
67
  from RepoAuditor.Query import ExecutionStyle, Query
@@ -149,7 +150,7 @@ class ClassicBranchProtectionQuery(Query):
149
150
  # and then see if rule sets are in use if the classic information is not found.
150
151
  response = module_data["session"].get(f"/branches/{module_data['branch']}/protection")
151
152
 
152
- if response.status_code == 404:
153
+ if response.status_code == requests.codes.NOT_FOUND:
153
154
  # Does this branch use rule sets?
154
155
  ruleset_response = module_data["session"].get(f"rules/branches/{module_data['branch']}")
155
156
 
@@ -24,7 +24,7 @@ class EnableRequirementImpl(Requirement):
24
24
  """Object that implements settings that can be enabled/disabled."""
25
25
 
26
26
  # ----------------------------------------------------------------------
27
- def __init__(
27
+ def __init__( # noqa: PLR0913
28
28
  self,
29
29
  name: str,
30
30
  default_value: bool, # noqa: FBT001
@@ -19,7 +19,7 @@ class StandardEnableRequirementImpl(EnableRequirementImpl):
19
19
  """Implementation of requirement for standard enables of GitHub settings."""
20
20
 
21
21
  # ----------------------------------------------------------------------
22
- def __init__(
22
+ def __init__( # noqa: PLR0913
23
23
  self,
24
24
  name: str,
25
25
  default_value: bool, # noqa: FBT001
@@ -104,7 +104,8 @@ class _GitHubSession(requests.Session):
104
104
  url_parts = urlparse(github_url)
105
105
  path_parts = url_parts.path.split("/")
106
106
 
107
- if len(path_parts) != 3:
107
+ # The URL should be of the form <github_server>/<username>/<repo>
108
+ if len(path_parts) != 3: # noqa: PLR2004
108
109
  msg = f"'{github_url}' is not a valid GitHub repository URL."
109
110
  raise ValueError(msg)
110
111
 
@@ -7,6 +7,8 @@
7
7
  """Contains the CustomizationQuery object."""
8
8
 
9
9
  from typing import Any, Optional
10
+ from tempfile import TemporaryDirectory
11
+ from git import Repo
10
12
 
11
13
  from dbrownell_Common.Types import override # type: ignore[import-untyped]
12
14
 
@@ -40,12 +42,22 @@ class CustomizationQuery(Query):
40
42
  self,
41
43
  module_data: dict[str, Any],
42
44
  ) -> Optional[dict[str, Any]]:
43
- """Get the data from an API session."""
44
- response = module_data["session"].get("")
45
+ """Get the repo data."""
45
46
 
46
- response.raise_for_status()
47
- response = response.json()
47
+ # Clone the GitHub repository to a temp directory
48
+ github_url = module_data["url"]
49
+ branch = module_data.get("branch", "main")
50
+ temp_repo_dir = TemporaryDirectory()
51
+ Repo.clone_from(github_url, temp_repo_dir.name, branch=branch)
48
52
 
49
- module_data["standard"] = response
53
+ # Record the path and the temp directory for later cleanup
54
+ module_data["repo_dir"] = temp_repo_dir
50
55
 
51
56
  return module_data
57
+
58
+ @override
59
+ def Cleanup(self, module_data: dict[str, Any]) -> None:
60
+ """Clean up the cloned repository."""
61
+ repo_dir = module_data["repo_dir"]
62
+ repo_dir.cleanup()
63
+ del module_data
@@ -6,6 +6,7 @@
6
6
  # -------------------------------------------------------------------------------
7
7
  """Contains the ExistsRequirementImpl object."""
8
8
 
9
+ from pathlib import Path
9
10
  from typing import Any
10
11
  from collections.abc import Sequence
11
12
 
@@ -69,28 +70,23 @@ class ExistsRequirementImpl(Requirement):
69
70
  ) -> Requirement.EvaluateImplResult:
70
71
  if requirement_args[self.dynamic_arg_name]:
71
72
  for location in self.possible_locations:
72
- # Query for file location
73
- response = query_data["session"].get(f"contents/{location}")
73
+ # Get full file path in temporary repo directory and check if it exists
74
+ # This checks both upper case and lower case variants
75
+ full_file_path = Path(query_data["repo_dir"].name) / Path(location)
74
76
 
75
- # If location is found, response will have status code 200
76
- if response.status_code == 200:
77
- response_json = response.json()
78
- # If response is a list, we have a directory
79
- if isinstance(response_json, list):
80
- for file in response_json:
81
- # Check if there are any template files (.md or .yml)
82
- if ".md" in file["path"] or ".yml" in file["path"]:
83
- return Requirement.EvaluateImplResult(
84
- EvaluateResult.Success,
85
- f"File {self.github_file} found in directory {location}",
86
- )
87
-
88
- # If response is a dict, we have a single file
89
- elif isinstance(response_json, dict):
77
+ if full_file_path.exists():
78
+ # If full_file_path is a directory, check if it isn't empty
79
+ if full_file_path.is_dir() and any(full_file_path.iterdir()):
90
80
  return Requirement.EvaluateImplResult(
91
- EvaluateResult.Success, f"File {self.github_file} found at {location}"
81
+ EvaluateResult.Success,
82
+ f"File found in {self.github_file} directory of the repository",
92
83
  )
93
84
 
85
+ return Requirement.EvaluateImplResult(
86
+ EvaluateResult.Success,
87
+ f"{self.github_file} found in repository",
88
+ )
89
+
94
90
  return Requirement.EvaluateImplResult(
95
91
  EvaluateResult.Error,
96
92
  f"No {self.github_file} file found.",
@@ -6,9 +6,6 @@
6
6
  # -------------------------------------------------------------------------------
7
7
  """Contains the GitHubCustomizationModule object."""
8
8
 
9
- from typing import Any
10
- from dbrownell_Common.Types import override
11
-
12
9
  from RepoAuditor.Module import ExecutionStyle
13
10
  from RepoAuditor.Plugins.GitHubBase.Module import GitHubBaseModule
14
11
  from RepoAuditor.Plugins.GitHubCustomization.CustomizationQuery import CustomizationQuery
@@ -27,8 +24,3 @@ class GitHubCustomizationModule(GitHubBaseModule):
27
24
  ],
28
25
  requires_explicit_include=True,
29
26
  )
30
-
31
- @override
32
- def Cleanup(self, dynamic_args: dict[str, Any]) -> None:
33
- """Clean up any resources created during execution."""
34
- # No resources to clean up in the minimal implementation
@@ -20,14 +20,9 @@ class CodeOwners(ExistsRequirementImpl):
20
20
  "exists",
21
21
  "CODEOWNERS",
22
22
  [
23
- # Upper case variants
24
23
  ".github/CODEOWNERS",
25
24
  "docs/CODEOWNERS",
26
25
  "CODEOWNERS",
27
- # Lower case variants
28
- ".github/codeowners",
29
- "docs/codeowners",
30
- "codeowners",
31
26
  ],
32
27
  textwrap.dedent(
33
28
  """\
@@ -20,14 +20,9 @@ class Contributing(ExistsRequirementImpl):
20
20
  "exists",
21
21
  "CONTRIBUTING",
22
22
  [
23
- # Upper case variants
24
23
  ".github/CONTRIBUTING.md",
25
24
  "docs/CONTRIBUTING.md",
26
25
  "CONTRIBUTING.md",
27
- # Lower case variants
28
- ".github/contributing.md",
29
- "docs/contributing.md",
30
- "contributing.md",
31
26
  ],
32
27
  textwrap.dedent(
33
28
  """\
@@ -21,12 +21,8 @@ class IssueTemplates(ExistsRequirementImpl):
21
21
  ".github/ISSUE_TEMPLATE.md",
22
22
  "docs/ISSUE_TEMPLATE.md",
23
23
  "ISSUE_TEMPLATE.md",
24
- "docs/issue_template.md",
25
- ".github/issue_template.md",
26
- "issue_template.md",
27
24
  # Directories
28
25
  ".github/ISSUE_TEMPLATE",
29
- ".github/issue_template",
30
26
  ],
31
27
  "Add issue templates to your repository in the .github/ISSUE_TEMPLATE directory.",
32
28
  "Issue templates help contributors create high-quality issues by providing a structured format.",
@@ -18,17 +18,11 @@ class PullRequestTemplate(ExistsRequirementImpl):
18
18
  "exists",
19
19
  "PULL_REQUESTS_TEMPLATE",
20
20
  [
21
- # Upper case variants
22
21
  ".github/PULL_REQUEST_TEMPLATE.md",
23
22
  "docs/PULL_REQUEST_TEMPLATE.md",
24
23
  "PULL_REQUEST_TEMPLATE.md",
25
- # Lower case variants
26
- ".github/pull_request_template.md",
27
- "docs/pull_request_template.md",
28
- "pull_request_template.md",
29
24
  # Directory with multiple templates
30
25
  ".github/PULL_REQUEST_TEMPLATE",
31
- ".github/pull_request_template",
32
26
  ],
33
27
  "Create a pull request template file in one of these locations: .github/PULL_REQUEST_TEMPLATE.md, .github/pull_request_template.md, docs/PULL_REQUEST_TEMPLATE.md, or PULL_REQUEST_TEMPLATE.md",
34
28
  "Pull request templates help standardize code contributions and expedite the review process by ensuring consistent PR format.",
@@ -20,14 +20,9 @@ class SecurityPolicy(ExistsRequirementImpl):
20
20
  "exists",
21
21
  "SECURITY",
22
22
  [
23
- # Upper case variants
24
23
  ".github/SECURITY.md",
25
24
  "docs/SECURITY.md",
26
25
  "SECURITY.md",
27
- # Lower case variants
28
- ".github/security.md",
29
- "docs/security.md",
30
- "security.md",
31
26
  ],
32
27
  textwrap.dedent(
33
28
  """\
@@ -20,7 +20,7 @@ class EnableRulesetRequirementImpl(EnableRequirementImpl):
20
20
  """Object that implements ruleset settings that can be enabled/disabled."""
21
21
 
22
22
  # ----------------------------------------------------------------------
23
- def __init__(
23
+ def __init__( # noqa: PLR0913
24
24
  self,
25
25
  name: str,
26
26
  default_value: bool, # noqa: FBT001
@@ -129,6 +129,14 @@ class Query(ABC):
129
129
  max_num_threads=max_num_threads,
130
130
  )
131
131
 
132
+ # ----------------------------------------------------------------------
133
+ def Cleanup(
134
+ self,
135
+ module_data: dict[str, Any],
136
+ ) -> None:
137
+ """Clean up any resources created during execution."""
138
+ del module_data
139
+
132
140
 
133
141
  # ----------------------------------------------------------------------
134
142
  class StatusInfo:
@@ -3,4 +3,4 @@ APP_NAME = "RepoAuditor"
3
3
  # Note that this value will be overwritten by calls to `python ../../Build.py update_version` based
4
4
  # on changes observed in the git repository. The default value below will be used until the value
5
5
  # here is explicitly updated by the Continuous Integration system.
6
- __version__ = "0.2.28"
6
+ __version__ = "0.2.30"
@@ -36,11 +36,18 @@ class TestCustomization:
36
36
 
37
37
  def test_NoCodeOwners(self, pat_args, snapshot):
38
38
  """Test if a CODEOWNERS file does not exist in the repository."""
39
- # TODO: How to test if CodeOwners file doesn't exist without updating repo?
40
- result = CliRunner().invoke(app, pat_args)
41
-
42
- assert result.exit_code == 0, result.output
43
- # assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
39
+ result = CliRunner().invoke(
40
+ app,
41
+ pat_args
42
+ + [
43
+ "--GitHubCustomization-CodeOwners-exists",
44
+ "--GitHubCustomization-branch",
45
+ "test-GitHubCustomization",
46
+ ],
47
+ )
48
+
49
+ assert result.exit_code == -1, result.output
50
+ assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
44
51
 
45
52
  def test_Contributing(self, pat_args, snapshot):
46
53
  """Test if a CONTRIBUTING.md file exists in the repository."""
@@ -49,6 +56,21 @@ class TestCustomization:
49
56
  assert result.exit_code == 0, result.output
50
57
  assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
51
58
 
59
+ def test_NoContributing(self, pat_args, snapshot):
60
+ """Test if a CONTRIBUTING file does not exist in the repository."""
61
+ result = CliRunner().invoke(
62
+ app,
63
+ pat_args
64
+ + [
65
+ "--GitHubCustomization-Contributing-exists",
66
+ "--GitHubCustomization-branch",
67
+ "test-GitHubCustomization",
68
+ ],
69
+ )
70
+
71
+ assert result.exit_code == -1, result.output
72
+ assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
73
+
52
74
  def test_IssueTemplate(self, pat_args, snapshot):
53
75
  """Test if an Issue template file (e.g. ISSUE_TEMPLATE.md) exists in the repository."""
54
76
  result = CliRunner().invoke(app, pat_args + ["--GitHubCustomization-IssueTemplates-exists"])
@@ -56,6 +78,21 @@ class TestCustomization:
56
78
  assert result.exit_code == 0, result.output
57
79
  assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
58
80
 
81
+ def test_NoIssueTemplate(self, pat_args, snapshot):
82
+ """Test if no Issue template file exists in the repository."""
83
+ result = CliRunner().invoke(
84
+ app,
85
+ pat_args
86
+ + [
87
+ "--GitHubCustomization-IssueTemplates-exists",
88
+ "--GitHubCustomization-branch",
89
+ "test-GitHubCustomization",
90
+ ],
91
+ )
92
+
93
+ assert result.exit_code == -1, result.output
94
+ assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
95
+
59
96
  def test_PullRequestTemplate(self, pat_args, snapshot):
60
97
  """Test if a Pull Request template file (e.g. PULL_REQUEST_TEMPLATE.md) exists in the repository."""
61
98
  result = CliRunner().invoke(app, pat_args + ["--GitHubCustomization-PullRequestTemplate-exists"])
@@ -63,6 +100,21 @@ class TestCustomization:
63
100
  assert result.exit_code == 0, result.output
64
101
  assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
65
102
 
103
+ def test_NoPullRequestTemplate(self, pat_args, snapshot):
104
+ """Test if no Pull Request template file exists in the repository."""
105
+ result = CliRunner().invoke(
106
+ app,
107
+ pat_args
108
+ + [
109
+ "--GitHubCustomization-PullRequestTemplate-exists",
110
+ "--GitHubCustomization-branch",
111
+ "test-GitHubCustomization",
112
+ ],
113
+ )
114
+
115
+ assert result.exit_code == -1, result.output
116
+ assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
117
+
66
118
  def test_SecurityPolicy(self, pat_args, snapshot):
67
119
  """Test if a Security policy file (e.g. SECURITY.md) exists in the repository."""
68
120
  result = CliRunner().invoke(app, pat_args + ["--GitHubCustomization-SecurityPolicy-exists"])
@@ -70,6 +122,21 @@ class TestCustomization:
70
122
  assert result.exit_code == 0, result.output
71
123
  assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
72
124
 
125
+ def test_NoSecurityPolicy(self, pat_args, snapshot):
126
+ """Test if no Security policy file exists in the repository."""
127
+ result = CliRunner().invoke(
128
+ app,
129
+ pat_args
130
+ + [
131
+ "--GitHubCustomization-SecurityPolicy-exists",
132
+ "--GitHubCustomization-branch",
133
+ "test-GitHubCustomization",
134
+ ],
135
+ )
136
+
137
+ assert result.exit_code == -1, result.output
138
+ assert ScrubDurationGithuburlAndSpaces(result.stdout) == snapshot
139
+
73
140
 
74
141
  # ----------------------------------------------------------------------
75
142
  # ----------------------------------------------------------------------