crackerjack 0.33.0__py3-none-any.whl → 0.33.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (198) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +4 -13
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +104 -204
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +171 -174
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +44 -8
  74. crackerjack/managers/test_command_builder.py +1 -15
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +98 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +17 -16
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +173 -32
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +8 -10
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +0 -2
  109. crackerjack/mixins/error_handling.py +1 -70
  110. crackerjack/models/config.py +12 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +122 -122
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  115. crackerjack/monitoring/metrics_collector.py +426 -0
  116. crackerjack/monitoring/regression_prevention.py +8 -8
  117. crackerjack/monitoring/websocket_server.py +643 -0
  118. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  119. crackerjack/orchestration/coverage_improvement.py +3 -3
  120. crackerjack/orchestration/execution_strategies.py +26 -6
  121. crackerjack/orchestration/test_progress_streamer.py +8 -5
  122. crackerjack/plugins/base.py +2 -2
  123. crackerjack/plugins/hooks.py +7 -0
  124. crackerjack/plugins/managers.py +11 -8
  125. crackerjack/security/__init__.py +0 -1
  126. crackerjack/security/audit.py +6 -35
  127. crackerjack/services/anomaly_detector.py +392 -0
  128. crackerjack/services/api_extractor.py +615 -0
  129. crackerjack/services/backup_service.py +2 -2
  130. crackerjack/services/bounded_status_operations.py +15 -152
  131. crackerjack/services/cache.py +127 -1
  132. crackerjack/services/changelog_automation.py +395 -0
  133. crackerjack/services/config.py +15 -9
  134. crackerjack/services/config_merge.py +19 -80
  135. crackerjack/services/config_template.py +506 -0
  136. crackerjack/services/contextual_ai_assistant.py +48 -22
  137. crackerjack/services/coverage_badge_service.py +171 -0
  138. crackerjack/services/coverage_ratchet.py +27 -25
  139. crackerjack/services/debug.py +3 -3
  140. crackerjack/services/dependency_analyzer.py +460 -0
  141. crackerjack/services/dependency_monitor.py +14 -11
  142. crackerjack/services/documentation_generator.py +491 -0
  143. crackerjack/services/documentation_service.py +675 -0
  144. crackerjack/services/enhanced_filesystem.py +6 -5
  145. crackerjack/services/enterprise_optimizer.py +865 -0
  146. crackerjack/services/error_pattern_analyzer.py +676 -0
  147. crackerjack/services/file_hasher.py +1 -1
  148. crackerjack/services/git.py +8 -25
  149. crackerjack/services/health_metrics.py +10 -8
  150. crackerjack/services/heatmap_generator.py +735 -0
  151. crackerjack/services/initialization.py +11 -30
  152. crackerjack/services/input_validator.py +5 -97
  153. crackerjack/services/intelligent_commit.py +327 -0
  154. crackerjack/services/log_manager.py +15 -12
  155. crackerjack/services/logging.py +4 -3
  156. crackerjack/services/lsp_client.py +628 -0
  157. crackerjack/services/memory_optimizer.py +19 -87
  158. crackerjack/services/metrics.py +42 -33
  159. crackerjack/services/parallel_executor.py +9 -67
  160. crackerjack/services/pattern_cache.py +1 -1
  161. crackerjack/services/pattern_detector.py +6 -6
  162. crackerjack/services/performance_benchmarks.py +18 -59
  163. crackerjack/services/performance_cache.py +20 -81
  164. crackerjack/services/performance_monitor.py +27 -95
  165. crackerjack/services/predictive_analytics.py +510 -0
  166. crackerjack/services/quality_baseline.py +234 -0
  167. crackerjack/services/quality_baseline_enhanced.py +646 -0
  168. crackerjack/services/quality_intelligence.py +785 -0
  169. crackerjack/services/regex_patterns.py +605 -524
  170. crackerjack/services/regex_utils.py +43 -123
  171. crackerjack/services/secure_path_utils.py +5 -164
  172. crackerjack/services/secure_status_formatter.py +30 -141
  173. crackerjack/services/secure_subprocess.py +11 -92
  174. crackerjack/services/security.py +9 -41
  175. crackerjack/services/security_logger.py +12 -24
  176. crackerjack/services/server_manager.py +124 -16
  177. crackerjack/services/status_authentication.py +16 -159
  178. crackerjack/services/status_security_manager.py +4 -131
  179. crackerjack/services/thread_safe_status_collector.py +19 -125
  180. crackerjack/services/unified_config.py +21 -13
  181. crackerjack/services/validation_rate_limiter.py +5 -54
  182. crackerjack/services/version_analyzer.py +459 -0
  183. crackerjack/services/version_checker.py +1 -1
  184. crackerjack/services/websocket_resource_limiter.py +10 -144
  185. crackerjack/services/zuban_lsp_service.py +390 -0
  186. crackerjack/slash_commands/__init__.py +2 -7
  187. crackerjack/slash_commands/run.md +2 -2
  188. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  189. crackerjack/tools/validate_regex_patterns.py +19 -48
  190. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +196 -25
  191. crackerjack-0.33.1.dist-info/RECORD +229 -0
  192. crackerjack/CLAUDE.md +0 -207
  193. crackerjack/RULES.md +0 -380
  194. crackerjack/py313.py +0 -234
  195. crackerjack-0.33.0.dist-info/RECORD +0 -187
  196. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
  197. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
  198. {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,327 @@
1
+ """Intelligent commit message generation service."""
2
+
3
+ import re
4
+ import typing as t
5
+ from pathlib import Path
6
+
7
+ from rich.console import Console
8
+
9
+ from crackerjack.models.protocols import GitInterface
10
+
11
+ from .regex_patterns import CompiledPatternCache
12
+
13
+
14
+ class CommitMessageGenerator:
15
+ """Generate intelligent commit messages based on changes and context."""
16
+
17
+ def __init__(self, console: Console, git_service: GitInterface) -> None:
18
+ """Initialize commit message generator."""
19
+ self.console = console
20
+ self.git = git_service
21
+
22
+ # Common change type patterns
23
+ self.patterns = {
24
+ "feat": [
25
+ r"add|create|implement|introduce",
26
+ r"new.*feature",
27
+ r"support.*for",
28
+ ],
29
+ "fix": [
30
+ r"fix|resolve|correct|repair",
31
+ r"bug|issue|problem",
32
+ r"error|exception|failure",
33
+ ],
34
+ "refactor": [
35
+ r"refactor|restructure|reorganize",
36
+ r"extract|move|rename",
37
+ r"improve.*structure",
38
+ ],
39
+ "test": [
40
+ r"test|spec|fixture",
41
+ r"coverage|assertion",
42
+ r"mock|stub",
43
+ ],
44
+ "docs": [
45
+ r"readme|documentation|doc",
46
+ r"comment|docstring",
47
+ r"\.md$|\.rst$|\.txt$",
48
+ ],
49
+ "style": [
50
+ r"format|style|lint",
51
+ r"whitespace|indentation",
52
+ r"prettier|black|ruff",
53
+ ],
54
+ "chore": [
55
+ r"config|setup|build",
56
+ r"dependency|requirement",
57
+ r"version|release",
58
+ ],
59
+ }
60
+
61
+ def generate_commit_message(
62
+ self,
63
+ include_body: bool = True,
64
+ conventional_commits: bool = True,
65
+ ) -> str:
66
+ """Generate an intelligent commit message based on staged changes."""
67
+ try:
68
+ # Get changed files and their changes
69
+ staged_files = self.git.get_staged_files()
70
+ if not staged_files:
71
+ return "chore: no changes to commit"
72
+
73
+ # Analyze file changes
74
+ change_analysis = self._analyze_changes(staged_files)
75
+
76
+ # Generate message components
77
+ commit_type = self._determine_commit_type(change_analysis)
78
+ scope = self._determine_scope(change_analysis)
79
+ subject = self._generate_subject(change_analysis)
80
+
81
+ # Build commit message
82
+ if conventional_commits:
83
+ header = self._build_conventional_header(commit_type, scope, subject)
84
+ else:
85
+ header = subject
86
+
87
+ if not include_body:
88
+ return header
89
+
90
+ # Add body with details
91
+ body = self._generate_body(change_analysis)
92
+
93
+ if body:
94
+ return f"{header}\n\n{body}"
95
+
96
+ return header
97
+
98
+ except Exception as e:
99
+ self.console.print(
100
+ f"[yellow]⚠️[/yellow] Error generating commit message: {e}"
101
+ )
102
+ return "chore: update files"
103
+
104
+ def _analyze_changes(self, staged_files: list[str]) -> dict[str, t.Any]:
105
+ """Analyze staged files to understand the nature of changes."""
106
+ analysis: dict[str, t.Any] = {
107
+ "files": staged_files,
108
+ "file_types": set(),
109
+ "directories": set(),
110
+ "total_files": len(staged_files),
111
+ "patterns_found": set(),
112
+ }
113
+
114
+ for file_path in staged_files:
115
+ path = Path(file_path)
116
+
117
+ # Track file types
118
+ if path.suffix:
119
+ analysis["file_types"].add(path.suffix)
120
+
121
+ # Track directories
122
+ if path.parent != Path():
123
+ analysis["directories"].add(str(path.parent))
124
+
125
+ # Check for patterns in file names
126
+ file_str = str(path).lower()
127
+ for commit_type, patterns in self.patterns.items():
128
+ for pattern in patterns:
129
+ # Use safe compiled pattern cache instead of raw re.search
130
+ compiled_pattern = (
131
+ CompiledPatternCache.get_compiled_pattern_with_flags(
132
+ f"commit_{commit_type}_{pattern}", pattern, re.IGNORECASE
133
+ )
134
+ )
135
+ if compiled_pattern.search(file_str):
136
+ analysis["patterns_found"].add(commit_type)
137
+
138
+ return analysis
139
+
140
+ def _determine_commit_type(self, analysis: dict[str, t.Any]) -> str:
141
+ """Determine the most appropriate commit type."""
142
+ patterns_found = analysis["patterns_found"]
143
+ files = analysis["files"]
144
+ file_types = analysis["file_types"]
145
+
146
+ # Check commit types in priority order
147
+ commit_type_checks = self._get_commit_type_checks()
148
+
149
+ for commit_type, check_func in commit_type_checks:
150
+ if check_func(patterns_found, files, file_types):
151
+ return commit_type
152
+
153
+ # Default to chore for misc changes
154
+ return "chore"
155
+
156
+ def _get_commit_type_checks(self) -> list[tuple[str, t.Callable[..., t.Any]]]:
157
+ """Get ordered list[t.Any] of commit type checks."""
158
+ return [
159
+ ("fix", self._is_fix_commit),
160
+ ("feat", self._is_feat_commit),
161
+ ("test", self._is_test_commit),
162
+ ("docs", self._is_docs_commit),
163
+ ("style", self._is_style_commit),
164
+ ("refactor", self._is_refactor_commit),
165
+ ]
166
+
167
+ def _is_fix_commit(
168
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
169
+ ) -> bool:
170
+ """Check if this is a fix commit."""
171
+ return "fix" in patterns
172
+
173
+ def _is_feat_commit(
174
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
175
+ ) -> bool:
176
+ """Check if this is a feature commit."""
177
+ return "feat" in patterns
178
+
179
+ def _is_test_commit(
180
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
181
+ ) -> bool:
182
+ """Check if this is a test commit."""
183
+ return "test" in patterns or any(
184
+ ".py" in f and "test" in f.lower() for f in files
185
+ )
186
+
187
+ def _is_docs_commit(
188
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
189
+ ) -> bool:
190
+ """Check if this is a documentation commit."""
191
+ return "docs" in patterns or any(
192
+ ext in file_types for ext in (".md", ".rst", ".txt")
193
+ )
194
+
195
+ def _is_style_commit(
196
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
197
+ ) -> bool:
198
+ """Check if this is a style commit."""
199
+ return (
200
+ "style" in patterns or len(files) > 5
201
+ ) # Multiple files suggest style changes
202
+
203
+ def _is_refactor_commit(
204
+ self, patterns: set[t.Any], files: list[t.Any], file_types: set[t.Any]
205
+ ) -> bool:
206
+ """Check if this is a refactor commit."""
207
+ return "refactor" in patterns
208
+
209
+ def _determine_scope(self, analysis: dict[str, t.Any]) -> str | None:
210
+ """Determine an appropriate scope for the commit."""
211
+ directories = analysis["directories"]
212
+ files = analysis["files"]
213
+
214
+ if len(directories) == 1:
215
+ # Single directory - use as scope
216
+ directory = list[str](directories)[0]
217
+ # Simplify common directory patterns
218
+ if "/" in directory:
219
+ return directory.split("/")[0] # Use top-level directory
220
+ return directory
221
+
222
+ # Check for common patterns
223
+ if any("test" in f.lower() for f in files):
224
+ return "test"
225
+ if any("doc" in f.lower() for f in files):
226
+ return "docs"
227
+ if any(f.endswith(".py") for f in files):
228
+ return "core"
229
+ if any(f.endswith((".yml", ".yaml", ".toml", ".json")) for f in files):
230
+ return "config"
231
+
232
+ # No clear scope
233
+ return None
234
+
235
+ def _generate_subject(self, analysis: dict[str, t.Any]) -> str:
236
+ """Generate a descriptive subject line."""
237
+ files = analysis["files"]
238
+ file_types = analysis["file_types"]
239
+ total_files = analysis["total_files"]
240
+
241
+ # Handle single file changes
242
+ if total_files == 1:
243
+ file_path = Path(files[0])
244
+ file_name = file_path.stem
245
+
246
+ # Generate descriptive action based on file name
247
+ if "test" in file_name.lower():
248
+ return f"update {file_name} test"
249
+ elif file_path.suffix in (".md", ".rst", ".txt"):
250
+ return f"update {file_name} documentation"
251
+ elif "config" in file_name.lower():
252
+ return f"update {file_name} configuration"
253
+ else:
254
+ return f"update {file_name}"
255
+
256
+ # Handle multiple files
257
+ if total_files <= 3:
258
+ # List specific files
259
+ file_names = [Path(f).stem for f in files]
260
+ return f"update {', '.join(file_names)}"
261
+
262
+ # Handle bulk changes
263
+ if len(file_types) == 1:
264
+ file_type = list[t.Any](file_types)[0]
265
+ return f"update {total_files} {file_type} files"
266
+
267
+ return f"update {total_files} files"
268
+
269
+ def _build_conventional_header(
270
+ self, commit_type: str, scope: str | None, subject: str
271
+ ) -> str:
272
+ """Build conventional commit header format."""
273
+ if scope:
274
+ return f"{commit_type}({scope}): {subject}"
275
+ return f"{commit_type}: {subject}"
276
+
277
+ def _generate_body(self, analysis: dict[str, t.Any]) -> str:
278
+ """Generate detailed commit body."""
279
+ files = analysis["files"]
280
+ total_files = analysis["total_files"]
281
+
282
+ if total_files <= 3:
283
+ # List specific files for small changes
284
+ body_lines = ["Modified files:"]
285
+ for file_path in sorted(files):
286
+ body_lines.append(f"- {file_path}")
287
+ return "\n".join(body_lines)
288
+
289
+ # Summarize for larger changes
290
+ directories = analysis["directories"]
291
+ file_types = analysis["file_types"]
292
+
293
+ body_lines = [f"Updated {total_files} files across:"]
294
+
295
+ if directories:
296
+ body_lines.append("Directories:")
297
+ for directory in sorted(directories):
298
+ body_lines.append(f"- {directory}")
299
+
300
+ if file_types:
301
+ body_lines.append("File types:")
302
+ for file_type in sorted(file_types):
303
+ body_lines.append(f"- {file_type}")
304
+
305
+ return "\n".join(body_lines)
306
+
307
+ def commit_with_generated_message(
308
+ self,
309
+ include_body: bool = True,
310
+ conventional_commits: bool = True,
311
+ dry_run: bool = False,
312
+ ) -> bool:
313
+ """Generate commit message and create commit."""
314
+ message = self.generate_commit_message(
315
+ include_body=include_body,
316
+ conventional_commits=conventional_commits,
317
+ )
318
+
319
+ if dry_run:
320
+ self.console.print("[cyan]📝[/cyan] Generated commit message:")
321
+ self.console.print(f"[dim]{message}[/dim]")
322
+ return True
323
+
324
+ self.console.print(
325
+ f"[cyan]📝[/cyan] Committing with message: {message.split(chr(10))[0]}"
326
+ )
327
+ return self.git.commit(message)
@@ -2,6 +2,7 @@ import logging
2
2
  import os
3
3
  import shutil
4
4
  import time
5
+ import typing as t
5
6
  from contextlib import suppress
6
7
  from pathlib import Path
7
8
 
@@ -141,7 +142,7 @@ class LogManager:
141
142
  return {"moved": 0, "failed": 0, "found": 0}
142
143
 
143
144
  debug_pattern = "crackerjack-debug-*.log"
144
- legacy_files = list(source_dir.glob(debug_pattern))
145
+ legacy_files = list[t.Any](source_dir.glob(debug_pattern))
145
146
 
146
147
  results = {"found": len(legacy_files), "moved": 0, "failed": 0}
147
148
 
@@ -184,8 +185,8 @@ class LogManager:
184
185
 
185
186
  return results
186
187
 
187
- def get_log_stats(self) -> dict[str, dict[str, int | str]]:
188
- stats = {}
188
+ def get_log_stats(self) -> dict[str, dict[str, int | str | float]]:
189
+ stats: dict[str, dict[str, int | str | float]] = {}
189
190
 
190
191
  for log_type, log_dir in (
191
192
  ("debug", self.debug_dir),
@@ -193,7 +194,7 @@ class LogManager:
193
194
  ("audit", self.audit_dir),
194
195
  ):
195
196
  if log_dir.exists():
196
- files = list(log_dir.glob("*.log"))
197
+ files = list[t.Any](log_dir.glob("*.log"))
197
198
  total_size = sum(f.stat().st_size for f in files if f.exists())
198
199
 
199
200
  stats[log_type] = {
@@ -250,17 +251,19 @@ class LogManager:
250
251
  console.print("\n[bold]📊 Log File Summary[/ bold]")
251
252
  console.print(f"[dim]Location: {self.log_dir}[/ dim]")
252
253
 
253
- total_files = 0
254
- total_size = 0.0
254
+ total_files: int = 0
255
+ total_size: float = 0.0
255
256
 
256
257
  for log_type, data in stats.items():
257
- count = (
258
- int(data["count"]) if isinstance(data["count"], str) else data["count"]
258
+ count_raw = data["count"]
259
+ count: int = (
260
+ int(count_raw) if isinstance(count_raw, str) else t.cast(int, count_raw)
259
261
  )
260
- size = (
261
- float(data["size_mb"])
262
- if isinstance(data["size_mb"], str)
263
- else data["size_mb"]
262
+ size_raw = data["size_mb"]
263
+ size: float = (
264
+ float(size_raw)
265
+ if isinstance(size_raw, str)
266
+ else t.cast(float, size_raw)
264
267
  )
265
268
 
266
269
  total_files += count
@@ -32,7 +32,7 @@ def add_correlation_id(_: Any, __: Any, event_dict: EventDict) -> EventDict:
32
32
 
33
33
 
34
34
  def add_timestamp(_: Any, __: Any, event_dict: EventDict) -> EventDict:
35
- event_dict["timestamp"] = time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
35
+ event_dict["timestamp"] = time.strftime("%Y-%m-%dT%H: %M: %S.%f")[:-3] + "Z"
36
36
  return event_dict
37
37
 
38
38
 
@@ -69,7 +69,7 @@ def setup_structured_logging(
69
69
  console_handler = logging.StreamHandler(sys.stdout)
70
70
  console_handler.setLevel(log_level)
71
71
 
72
- handlers = [console_handler]
72
+ handlers: list[logging.Handler] = [console_handler]
73
73
 
74
74
  if log_file:
75
75
  log_file.parent.mkdir(parents=True, exist_ok=True)
@@ -85,7 +85,8 @@ def setup_structured_logging(
85
85
 
86
86
 
87
87
  def get_logger(name: str) -> structlog.BoundLogger:
88
- return structlog.get_logger(name)
88
+ logger: structlog.BoundLogger = structlog.get_logger(name)
89
+ return logger
89
90
 
90
91
 
91
92
  class LoggingContext: