crackerjack 0.31.10__py3-none-any.whl → 0.31.13__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.
- crackerjack/CLAUDE.md +288 -705
- crackerjack/__main__.py +22 -8
- crackerjack/agents/__init__.py +0 -3
- crackerjack/agents/architect_agent.py +0 -43
- crackerjack/agents/base.py +1 -9
- crackerjack/agents/coordinator.py +2 -148
- crackerjack/agents/documentation_agent.py +109 -81
- crackerjack/agents/dry_agent.py +122 -97
- crackerjack/agents/formatting_agent.py +3 -16
- crackerjack/agents/import_optimization_agent.py +1174 -130
- crackerjack/agents/performance_agent.py +956 -188
- crackerjack/agents/performance_helpers.py +229 -0
- crackerjack/agents/proactive_agent.py +1 -48
- crackerjack/agents/refactoring_agent.py +516 -246
- crackerjack/agents/refactoring_helpers.py +282 -0
- crackerjack/agents/security_agent.py +393 -90
- crackerjack/agents/test_creation_agent.py +1776 -120
- crackerjack/agents/test_specialist_agent.py +59 -15
- crackerjack/agents/tracker.py +0 -102
- crackerjack/api.py +145 -37
- crackerjack/cli/handlers.py +48 -30
- crackerjack/cli/interactive.py +11 -11
- crackerjack/cli/options.py +66 -4
- crackerjack/code_cleaner.py +808 -148
- crackerjack/config/global_lock_config.py +110 -0
- crackerjack/config/hooks.py +43 -64
- crackerjack/core/async_workflow_orchestrator.py +247 -97
- crackerjack/core/autofix_coordinator.py +192 -109
- crackerjack/core/enhanced_container.py +46 -63
- crackerjack/core/file_lifecycle.py +549 -0
- crackerjack/core/performance.py +9 -8
- crackerjack/core/performance_monitor.py +395 -0
- crackerjack/core/phase_coordinator.py +281 -94
- crackerjack/core/proactive_workflow.py +9 -58
- crackerjack/core/resource_manager.py +501 -0
- crackerjack/core/service_watchdog.py +490 -0
- crackerjack/core/session_coordinator.py +4 -8
- crackerjack/core/timeout_manager.py +504 -0
- crackerjack/core/websocket_lifecycle.py +475 -0
- crackerjack/core/workflow_orchestrator.py +343 -209
- crackerjack/dynamic_config.py +50 -9
- crackerjack/errors.py +3 -4
- crackerjack/executors/async_hook_executor.py +63 -13
- crackerjack/executors/cached_hook_executor.py +14 -14
- crackerjack/executors/hook_executor.py +100 -37
- crackerjack/executors/hook_lock_manager.py +856 -0
- crackerjack/executors/individual_hook_executor.py +120 -86
- crackerjack/intelligence/__init__.py +0 -7
- crackerjack/intelligence/adaptive_learning.py +13 -86
- crackerjack/intelligence/agent_orchestrator.py +15 -78
- crackerjack/intelligence/agent_registry.py +12 -59
- crackerjack/intelligence/agent_selector.py +31 -92
- crackerjack/intelligence/integration.py +1 -41
- crackerjack/interactive.py +9 -9
- crackerjack/managers/async_hook_manager.py +25 -8
- crackerjack/managers/hook_manager.py +9 -9
- crackerjack/managers/publish_manager.py +57 -59
- crackerjack/managers/test_command_builder.py +6 -36
- crackerjack/managers/test_executor.py +9 -61
- crackerjack/managers/test_manager.py +17 -63
- crackerjack/managers/test_manager_backup.py +77 -127
- crackerjack/managers/test_progress.py +4 -23
- crackerjack/mcp/cache.py +5 -12
- crackerjack/mcp/client_runner.py +10 -10
- crackerjack/mcp/context.py +64 -6
- crackerjack/mcp/dashboard.py +14 -11
- crackerjack/mcp/enhanced_progress_monitor.py +55 -55
- crackerjack/mcp/file_monitor.py +72 -42
- crackerjack/mcp/progress_components.py +103 -84
- crackerjack/mcp/progress_monitor.py +122 -49
- crackerjack/mcp/rate_limiter.py +12 -12
- crackerjack/mcp/server_core.py +16 -22
- crackerjack/mcp/service_watchdog.py +26 -26
- crackerjack/mcp/state.py +15 -0
- crackerjack/mcp/tools/core_tools.py +95 -39
- crackerjack/mcp/tools/error_analyzer.py +6 -32
- crackerjack/mcp/tools/execution_tools.py +1 -56
- crackerjack/mcp/tools/execution_tools_backup.py +35 -131
- crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
- crackerjack/mcp/tools/intelligence_tools.py +2 -55
- crackerjack/mcp/tools/monitoring_tools.py +308 -145
- crackerjack/mcp/tools/proactive_tools.py +12 -42
- crackerjack/mcp/tools/progress_tools.py +23 -15
- crackerjack/mcp/tools/utility_tools.py +3 -40
- crackerjack/mcp/tools/workflow_executor.py +40 -60
- crackerjack/mcp/websocket/app.py +0 -3
- crackerjack/mcp/websocket/endpoints.py +206 -268
- crackerjack/mcp/websocket/jobs.py +213 -66
- crackerjack/mcp/websocket/server.py +84 -6
- crackerjack/mcp/websocket/websocket_handler.py +137 -29
- crackerjack/models/config_adapter.py +3 -16
- crackerjack/models/protocols.py +162 -3
- crackerjack/models/resource_protocols.py +454 -0
- crackerjack/models/task.py +3 -3
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +25 -71
- crackerjack/monitoring/regression_prevention.py +28 -87
- crackerjack/orchestration/advanced_orchestrator.py +44 -78
- crackerjack/orchestration/coverage_improvement.py +10 -60
- crackerjack/orchestration/execution_strategies.py +16 -16
- crackerjack/orchestration/test_progress_streamer.py +61 -53
- crackerjack/plugins/base.py +1 -1
- crackerjack/plugins/managers.py +22 -20
- crackerjack/py313.py +65 -21
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +627 -0
- crackerjack/services/cache.py +7 -9
- crackerjack/services/config.py +35 -52
- crackerjack/services/config_integrity.py +5 -16
- crackerjack/services/config_merge.py +542 -0
- crackerjack/services/contextual_ai_assistant.py +17 -19
- crackerjack/services/coverage_ratchet.py +44 -73
- crackerjack/services/debug.py +25 -39
- crackerjack/services/dependency_monitor.py +52 -50
- crackerjack/services/enhanced_filesystem.py +14 -11
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/filesystem.py +1 -12
- crackerjack/services/git.py +71 -47
- crackerjack/services/health_metrics.py +31 -27
- crackerjack/services/initialization.py +276 -428
- crackerjack/services/input_validator.py +760 -0
- crackerjack/services/log_manager.py +16 -16
- crackerjack/services/logging.py +7 -6
- crackerjack/services/metrics.py +43 -43
- crackerjack/services/pattern_cache.py +2 -31
- crackerjack/services/pattern_detector.py +26 -63
- crackerjack/services/performance_benchmarks.py +20 -45
- crackerjack/services/regex_patterns.py +2887 -0
- crackerjack/services/regex_utils.py +537 -0
- crackerjack/services/secure_path_utils.py +683 -0
- crackerjack/services/secure_status_formatter.py +534 -0
- crackerjack/services/secure_subprocess.py +605 -0
- crackerjack/services/security.py +47 -10
- crackerjack/services/security_logger.py +492 -0
- crackerjack/services/server_manager.py +109 -50
- crackerjack/services/smart_scheduling.py +8 -25
- crackerjack/services/status_authentication.py +603 -0
- crackerjack/services/status_security_manager.py +442 -0
- crackerjack/services/thread_safe_status_collector.py +546 -0
- crackerjack/services/tool_version_service.py +1 -23
- crackerjack/services/unified_config.py +36 -58
- crackerjack/services/validation_rate_limiter.py +269 -0
- crackerjack/services/version_checker.py +9 -40
- crackerjack/services/websocket_resource_limiter.py +572 -0
- crackerjack/slash_commands/__init__.py +52 -2
- crackerjack/tools/__init__.py +0 -0
- crackerjack/tools/validate_input_validator_patterns.py +262 -0
- crackerjack/tools/validate_regex_patterns.py +198 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/METADATA +197 -12
- crackerjack-0.31.13.dist-info/RECORD +178 -0
- crackerjack/cli/facade.py +0 -104
- crackerjack-0.31.10.dist-info/RECORD +0 -149
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/WHEEL +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.13.dist-info}/licenses/LICENSE +0 -0
crackerjack/services/config.py
CHANGED
|
@@ -15,18 +15,16 @@ class ConfigurationService:
|
|
|
15
15
|
self.config_generator = DynamicConfigGenerator()
|
|
16
16
|
|
|
17
17
|
def update_precommit_config(self, options: OptionsProtocol) -> bool:
|
|
18
|
-
"""Update pre-commit configuration and dynamic config versions."""
|
|
19
18
|
try:
|
|
20
|
-
# Generate config first
|
|
21
19
|
mode = self._determine_config_mode(options)
|
|
22
20
|
config_temp_path = generate_config_for_mode(mode)
|
|
23
21
|
if not config_temp_path:
|
|
24
|
-
self.console.print("[yellow]⚠️ No configuration generated[/yellow]")
|
|
22
|
+
self.console.print("[yellow]⚠️ No configuration generated[/ yellow]")
|
|
25
23
|
return False
|
|
26
24
|
|
|
27
25
|
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
28
26
|
config_content = config_temp_path.read_text()
|
|
29
|
-
|
|
27
|
+
|
|
30
28
|
from crackerjack.services.filesystem import FileSystemService
|
|
31
29
|
|
|
32
30
|
config_content = FileSystemService.clean_trailing_whitespace_and_newlines(
|
|
@@ -35,25 +33,23 @@ class ConfigurationService:
|
|
|
35
33
|
config_file.write_text(config_content)
|
|
36
34
|
|
|
37
35
|
self._temp_config_path = config_temp_path
|
|
38
|
-
self.console.print("[green]✅[/green] Pre-commit configuration generated")
|
|
36
|
+
self.console.print("[green]✅[/ green] Pre-commit configuration generated")
|
|
39
37
|
|
|
40
|
-
# Run pre-commit autoupdate if requested via -u flag
|
|
41
38
|
if getattr(options, "update_precommit", False):
|
|
42
39
|
success = self._run_precommit_autoupdate()
|
|
43
40
|
if success:
|
|
44
|
-
self.console.print("[green]✅[/green] Pre-commit hooks updated")
|
|
41
|
+
self.console.print("[green]✅[/ green] Pre-commit hooks updated")
|
|
45
42
|
else:
|
|
46
43
|
self.console.print(
|
|
47
|
-
"[yellow]⚠️[/yellow] Pre-commit autoupdate had issues"
|
|
44
|
+
"[yellow]⚠️[/ yellow] Pre-commit autoupdate had issues"
|
|
48
45
|
)
|
|
49
46
|
|
|
50
|
-
# Also update dynamic config versions
|
|
51
47
|
self._update_dynamic_config_versions()
|
|
52
48
|
|
|
53
49
|
return True
|
|
54
50
|
except Exception as e:
|
|
55
51
|
self.console.print(
|
|
56
|
-
f"[red]❌[/red] Failed to generate pre-commit config: {e}",
|
|
52
|
+
f"[red]❌[/ red] Failed to generate pre-commit config: {e}",
|
|
57
53
|
)
|
|
58
54
|
return False
|
|
59
55
|
|
|
@@ -72,7 +68,7 @@ class ConfigurationService:
|
|
|
72
68
|
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
73
69
|
if not config_file.exists():
|
|
74
70
|
self.console.print(
|
|
75
|
-
"[yellow]⚠️ No pre-commit configuration found[/yellow]",
|
|
71
|
+
"[yellow]⚠️ No pre-commit configuration found[/ yellow]",
|
|
76
72
|
)
|
|
77
73
|
return False
|
|
78
74
|
import yaml
|
|
@@ -84,10 +80,10 @@ class ConfigurationService:
|
|
|
84
80
|
if yaml_result is not None
|
|
85
81
|
else {}
|
|
86
82
|
)
|
|
87
|
-
self.console.print("[green]✅[/green] Pre-commit configuration is valid")
|
|
83
|
+
self.console.print("[green]✅[/ green] Pre-commit configuration is valid")
|
|
88
84
|
return True
|
|
89
85
|
except Exception as e:
|
|
90
|
-
self.console.print(f"[red]❌[/red] Configuration validation failed: {e}")
|
|
86
|
+
self.console.print(f"[red]❌[/ red] Configuration validation failed: {e}")
|
|
91
87
|
return False
|
|
92
88
|
|
|
93
89
|
def backup_config(self) -> Path | None:
|
|
@@ -101,12 +97,12 @@ class ConfigurationService:
|
|
|
101
97
|
backup_file = self.pkg_path / f".pre-commit-config.yaml.backup.{timestamp}"
|
|
102
98
|
backup_file.write_text(config_file.read_text())
|
|
103
99
|
self.console.print(
|
|
104
|
-
f"[cyan]💾[/cyan] Configuration backed up to {backup_file.name}",
|
|
100
|
+
f"[cyan]💾[/ cyan] Configuration backed up to {backup_file.name}",
|
|
105
101
|
)
|
|
106
102
|
return backup_file
|
|
107
103
|
except Exception as e:
|
|
108
104
|
self.console.print(
|
|
109
|
-
f"[yellow]⚠️[/yellow] Failed to backup configuration: {e}",
|
|
105
|
+
f"[yellow]⚠️[/ yellow] Failed to backup configuration: {e}",
|
|
110
106
|
)
|
|
111
107
|
return None
|
|
112
108
|
|
|
@@ -114,17 +110,17 @@ class ConfigurationService:
|
|
|
114
110
|
try:
|
|
115
111
|
if not backup_file.exists():
|
|
116
112
|
self.console.print(
|
|
117
|
-
f"[red]❌[/red] Backup file not found: {backup_file}",
|
|
113
|
+
f"[red]❌[/ red] Backup file not found: {backup_file}",
|
|
118
114
|
)
|
|
119
115
|
return False
|
|
120
116
|
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
121
117
|
config_file.write_text(backup_file.read_text())
|
|
122
118
|
self.console.print(
|
|
123
|
-
f"[green]✅[/green] Configuration restored from {backup_file.name}",
|
|
119
|
+
f"[green]✅[/ green] Configuration restored from {backup_file.name}",
|
|
124
120
|
)
|
|
125
121
|
return True
|
|
126
122
|
except Exception as e:
|
|
127
|
-
self.console.print(f"[red]❌[/red] Failed to restore configuration: {e}")
|
|
123
|
+
self.console.print(f"[red]❌[/ red] Failed to restore configuration: {e}")
|
|
128
124
|
return False
|
|
129
125
|
|
|
130
126
|
def get_config_info(self) -> dict[str, t.Any]:
|
|
@@ -172,7 +168,7 @@ class ConfigurationService:
|
|
|
172
168
|
try:
|
|
173
169
|
pyproject_file = self.pkg_path / "pyproject.toml"
|
|
174
170
|
if not pyproject_file.exists():
|
|
175
|
-
self.console.print("[yellow]⚠️ No pyproject.toml found[/yellow]")
|
|
171
|
+
self.console.print("[yellow]⚠️ No pyproject.toml found[/ yellow]")
|
|
176
172
|
return False
|
|
177
173
|
from tomllib import loads
|
|
178
174
|
|
|
@@ -192,7 +188,7 @@ class ConfigurationService:
|
|
|
192
188
|
"show-fixes": True,
|
|
193
189
|
"output-format": "full",
|
|
194
190
|
}
|
|
195
|
-
config["tool"]["ruff"]["format"] = {"docstring-code-format": True}
|
|
191
|
+
config["tool"]["ruff"]["format"] = {"docstring - code-format": True}
|
|
196
192
|
config["tool"]["ruff"]["lint"] = {
|
|
197
193
|
"extend-select": ["C901", "F", "I", "UP"],
|
|
198
194
|
"ignore": ["E402", "F821"],
|
|
@@ -203,7 +199,7 @@ class ConfigurationService:
|
|
|
203
199
|
"ini_options": {
|
|
204
200
|
"asyncio_mode": "auto",
|
|
205
201
|
"timeout": 300,
|
|
206
|
-
"addopts": "
|
|
202
|
+
"addopts": "- - cov=crackerjack - - cov-report=term",
|
|
207
203
|
"markers": [
|
|
208
204
|
"unit: marks test as a unit test",
|
|
209
205
|
"benchmark: mark test as a benchmark",
|
|
@@ -212,25 +208,26 @@ class ConfigurationService:
|
|
|
212
208
|
],
|
|
213
209
|
},
|
|
214
210
|
}
|
|
215
|
-
|
|
211
|
+
|
|
216
212
|
from crackerjack.services.filesystem import FileSystemService
|
|
217
213
|
|
|
218
214
|
content = dumps(config)
|
|
219
215
|
content = FileSystemService.clean_trailing_whitespace_and_newlines(content)
|
|
220
216
|
with pyproject_file.open("w") as f:
|
|
221
217
|
f.write(content)
|
|
222
|
-
self.console.print(
|
|
218
|
+
self.console.print(
|
|
219
|
+
"[green]✅[/ green] pyproject.toml configuration updated"
|
|
220
|
+
)
|
|
223
221
|
return True
|
|
224
222
|
except Exception as e:
|
|
225
|
-
self.console.print(f"[red]❌[/red] Failed to update pyproject.toml: {e}")
|
|
223
|
+
self.console.print(f"[red]❌[/ red] Failed to update pyproject.toml: {e}")
|
|
226
224
|
return False
|
|
227
225
|
|
|
228
226
|
def _run_precommit_autoupdate(self) -> bool:
|
|
229
|
-
"""Run pre-commit autoupdate to get latest hook versions."""
|
|
230
227
|
import subprocess
|
|
231
228
|
|
|
232
229
|
try:
|
|
233
|
-
self.console.print("[cyan]🔄[/cyan] Running pre-commit autoupdate...")
|
|
230
|
+
self.console.print("[cyan]🔄[/ cyan] Running pre-commit autoupdate...")
|
|
234
231
|
result = self._execute_precommit_autoupdate()
|
|
235
232
|
|
|
236
233
|
if result.returncode == 0:
|
|
@@ -241,17 +238,15 @@ class ConfigurationService:
|
|
|
241
238
|
return False
|
|
242
239
|
|
|
243
240
|
except subprocess.TimeoutExpired:
|
|
244
|
-
self.console.print("[red]❌[/red] Pre-commit autoupdate timed out")
|
|
241
|
+
self.console.print("[red]❌[/ red] Pre-commit autoupdate timed out")
|
|
245
242
|
return False
|
|
246
243
|
except Exception as e:
|
|
247
244
|
self.console.print(
|
|
248
|
-
f"[red]❌[/red] Failed to run pre-commit autoupdate: {e}"
|
|
245
|
+
f"[red]❌[/ red] Failed to run pre-commit autoupdate: {e}"
|
|
249
246
|
)
|
|
250
247
|
return False
|
|
251
248
|
|
|
252
249
|
def _execute_precommit_autoupdate(self) -> subprocess.CompletedProcess[str]:
|
|
253
|
-
"""Execute the pre-commit autoupdate command."""
|
|
254
|
-
|
|
255
250
|
return subprocess.run(
|
|
256
251
|
["uv", "run", "pre-commit", "autoupdate"],
|
|
257
252
|
cwd=self.pkg_path,
|
|
@@ -261,32 +256,27 @@ class ConfigurationService:
|
|
|
261
256
|
)
|
|
262
257
|
|
|
263
258
|
def _display_autoupdate_results(self, stdout: str) -> None:
|
|
264
|
-
"""Display updated versions if any."""
|
|
265
259
|
if self._has_updates(stdout):
|
|
266
260
|
for line in stdout.split("\n"):
|
|
267
261
|
if self._is_update_line(line):
|
|
268
|
-
self.console.print(f"[dim]
|
|
262
|
+
self.console.print(f"[dim] {line.strip()}[/ dim]")
|
|
269
263
|
|
|
270
264
|
def _has_updates(self, stdout: str) -> bool:
|
|
271
|
-
"""Check if the output contains update information."""
|
|
272
265
|
stdout_lower = stdout.lower()
|
|
273
266
|
return "updating" in stdout_lower or "updated" in stdout_lower
|
|
274
267
|
|
|
275
268
|
def _is_update_line(self, line: str) -> bool:
|
|
276
|
-
""
|
|
277
|
-
return "updating" in line.lower() or "->" in line
|
|
269
|
+
return "updating" in line.lower() or "- >" in line
|
|
278
270
|
|
|
279
271
|
def _handle_autoupdate_error(self, stderr: str) -> None:
|
|
280
|
-
"""Handle pre-commit autoupdate error output."""
|
|
281
272
|
if stderr:
|
|
282
273
|
self.console.print(
|
|
283
|
-
f"[yellow]Pre-commit autoupdate stderr:[/yellow] {stderr}"
|
|
274
|
+
f"[yellow]Pre-commit autoupdate stderr: [/ yellow] {stderr}"
|
|
284
275
|
)
|
|
285
276
|
|
|
286
277
|
def _update_dynamic_config_versions(self) -> None:
|
|
287
|
-
"""Update hardcoded versions in dynamic_config.py based on .pre-commit-config.yaml."""
|
|
288
278
|
try:
|
|
289
|
-
self.console.print("[cyan]🔄[/cyan] Updating dynamic config versions...")
|
|
279
|
+
self.console.print("[cyan]🔄[/ cyan] Updating dynamic config versions...")
|
|
290
280
|
|
|
291
281
|
version_updates = self._extract_version_updates()
|
|
292
282
|
if version_updates:
|
|
@@ -294,11 +284,10 @@ class ConfigurationService:
|
|
|
294
284
|
|
|
295
285
|
except Exception as e:
|
|
296
286
|
self.console.print(
|
|
297
|
-
f"[yellow]⚠️[/yellow] Failed to update dynamic config versions: {e}"
|
|
287
|
+
f"[yellow]⚠️[/ yellow] Failed to update dynamic config versions: {e}"
|
|
298
288
|
)
|
|
299
289
|
|
|
300
290
|
def _extract_version_updates(self) -> dict[str, str]:
|
|
301
|
-
"""Extract version mappings from .pre-commit-config.yaml."""
|
|
302
291
|
config_file = self.pkg_path / ".pre-commit-config.yaml"
|
|
303
292
|
if not config_file.exists():
|
|
304
293
|
return {}
|
|
@@ -322,7 +311,6 @@ class ConfigurationService:
|
|
|
322
311
|
return version_updates
|
|
323
312
|
|
|
324
313
|
def _update_dynamic_config_file(self, version_updates: dict[str, str]) -> None:
|
|
325
|
-
"""Update dynamic_config.py with version mappings."""
|
|
326
314
|
dynamic_config_path = self.pkg_path / "crackerjack" / "dynamic_config.py"
|
|
327
315
|
if dynamic_config_path.exists():
|
|
328
316
|
self._apply_version_updates(dynamic_config_path, version_updates)
|
|
@@ -330,29 +318,24 @@ class ConfigurationService:
|
|
|
330
318
|
def _apply_version_updates(
|
|
331
319
|
self, config_path: Path, version_updates: dict[str, str]
|
|
332
320
|
) -> None:
|
|
333
|
-
"""Apply version updates to dynamic_config.py."""
|
|
334
321
|
try:
|
|
335
322
|
content = config_path.read_text()
|
|
336
323
|
updated = False
|
|
337
324
|
|
|
338
325
|
for repo_url, new_rev in version_updates.items():
|
|
339
|
-
|
|
340
|
-
import re
|
|
341
|
-
|
|
342
|
-
pattern = rf'("repo": "{re.escape(repo_url)}".*?"rev": )"([^"]+)"'
|
|
343
|
-
replacement = rf'\1"{new_rev}"'
|
|
326
|
+
from .regex_patterns import update_repo_revision
|
|
344
327
|
|
|
345
|
-
new_content =
|
|
328
|
+
new_content = update_repo_revision(content, repo_url, new_rev)
|
|
346
329
|
if new_content != content:
|
|
347
330
|
content = new_content
|
|
348
331
|
updated = True
|
|
349
|
-
self.console.print(f"[dim]
|
|
332
|
+
self.console.print(f"[dim] Updated {repo_url} to {new_rev}[/ dim]")
|
|
350
333
|
|
|
351
334
|
if updated:
|
|
352
335
|
config_path.write_text(content)
|
|
353
|
-
self.console.print("[green]✅[/green] Dynamic config versions updated")
|
|
336
|
+
self.console.print("[green]✅[/ green] Dynamic config versions updated")
|
|
354
337
|
|
|
355
338
|
except Exception as e:
|
|
356
339
|
self.console.print(
|
|
357
|
-
f"[yellow]⚠️[/yellow] Failed to apply version updates: {e}"
|
|
340
|
+
f"[yellow]⚠️[/ yellow] Failed to apply version updates: {e}"
|
|
358
341
|
)
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
"""Configuration integrity checking service.
|
|
2
|
-
|
|
3
|
-
This module handles detection of configuration file changes and validates
|
|
4
|
-
required configuration sections. Split from tool_version_service.py.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
1
|
from pathlib import Path
|
|
8
2
|
|
|
9
3
|
from rich.console import Console
|
|
10
4
|
|
|
11
5
|
|
|
12
6
|
class ConfigIntegrityService:
|
|
13
|
-
"""Service for checking configuration file integrity and required sections."""
|
|
14
|
-
|
|
15
7
|
def __init__(self, console: Console, project_path: Path) -> None:
|
|
16
8
|
self.console = console
|
|
17
9
|
self.project_path = project_path
|
|
@@ -19,7 +11,6 @@ class ConfigIntegrityService:
|
|
|
19
11
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
20
12
|
|
|
21
13
|
def check_config_integrity(self) -> bool:
|
|
22
|
-
"""Check for configuration file drift and missing required sections."""
|
|
23
14
|
config_files = [
|
|
24
15
|
".pre-commit-config.yaml",
|
|
25
16
|
"pyproject.toml",
|
|
@@ -34,14 +25,13 @@ class ConfigIntegrityService:
|
|
|
34
25
|
|
|
35
26
|
if not self._has_required_config_sections():
|
|
36
27
|
self.console.print(
|
|
37
|
-
"[yellow]⚠️ Configuration missing required sections[/yellow]",
|
|
28
|
+
"[yellow]⚠️ Configuration missing required sections[/ yellow]",
|
|
38
29
|
)
|
|
39
30
|
drift_detected = True
|
|
40
31
|
|
|
41
32
|
return drift_detected
|
|
42
33
|
|
|
43
34
|
def _check_file_drift(self, file_path: Path) -> bool:
|
|
44
|
-
"""Check if a configuration file has been modified since last check."""
|
|
45
35
|
cache_file = self.cache_dir / f"{file_path.name}.hash"
|
|
46
36
|
|
|
47
37
|
try:
|
|
@@ -55,7 +45,7 @@ class ConfigIntegrityService:
|
|
|
55
45
|
cached_hash = int(cache_file.read_text().strip())
|
|
56
46
|
if current_hash != cached_hash:
|
|
57
47
|
self.console.print(
|
|
58
|
-
f"[yellow]⚠️ {file_path.name} has been modified manually[/yellow]",
|
|
48
|
+
f"[yellow]⚠️ {file_path.name} has been modified manually[/ yellow]",
|
|
59
49
|
)
|
|
60
50
|
return True
|
|
61
51
|
|
|
@@ -63,11 +53,10 @@ class ConfigIntegrityService:
|
|
|
63
53
|
return False
|
|
64
54
|
|
|
65
55
|
except OSError as e:
|
|
66
|
-
self.console.print(f"[red]❌ Error checking {file_path.name}: {e}[/red]")
|
|
56
|
+
self.console.print(f"[red]❌ Error checking {file_path.name}: {e}[/ red]")
|
|
67
57
|
return False
|
|
68
58
|
|
|
69
59
|
def _has_required_config_sections(self) -> bool:
|
|
70
|
-
"""Check if pyproject.toml has all required configuration sections."""
|
|
71
60
|
pyproject = self.project_path / "pyproject.toml"
|
|
72
61
|
if not pyproject.exists():
|
|
73
62
|
return False
|
|
@@ -87,7 +76,7 @@ class ConfigIntegrityService:
|
|
|
87
76
|
for key in keys:
|
|
88
77
|
if key not in current:
|
|
89
78
|
self.console.print(
|
|
90
|
-
f"[yellow]⚠️ Missing required config section: {section}[/yellow]",
|
|
79
|
+
f"[yellow]⚠️ Missing required config section: {section}[/ yellow]",
|
|
91
80
|
)
|
|
92
81
|
return False
|
|
93
82
|
current = current[key]
|
|
@@ -95,5 +84,5 @@ class ConfigIntegrityService:
|
|
|
95
84
|
return True
|
|
96
85
|
|
|
97
86
|
except Exception as e:
|
|
98
|
-
self.console.print(f"[red]❌ Error parsing pyproject.toml: {e}[/red]")
|
|
87
|
+
self.console.print(f"[red]❌ Error parsing pyproject.toml: {e}[/ red]")
|
|
99
88
|
return False
|