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.
- crackerjack/__main__.py +1350 -34
- crackerjack/adapters/__init__.py +17 -0
- crackerjack/adapters/lsp_client.py +358 -0
- crackerjack/adapters/rust_tool_adapter.py +194 -0
- crackerjack/adapters/rust_tool_manager.py +193 -0
- crackerjack/adapters/skylos_adapter.py +231 -0
- crackerjack/adapters/zuban_adapter.py +560 -0
- crackerjack/agents/base.py +7 -3
- crackerjack/agents/coordinator.py +271 -33
- crackerjack/agents/documentation_agent.py +9 -15
- crackerjack/agents/dry_agent.py +3 -15
- crackerjack/agents/formatting_agent.py +1 -1
- crackerjack/agents/import_optimization_agent.py +36 -180
- crackerjack/agents/performance_agent.py +17 -98
- crackerjack/agents/performance_helpers.py +7 -31
- crackerjack/agents/proactive_agent.py +1 -3
- crackerjack/agents/refactoring_agent.py +16 -85
- crackerjack/agents/refactoring_helpers.py +7 -42
- crackerjack/agents/security_agent.py +9 -48
- crackerjack/agents/test_creation_agent.py +356 -513
- crackerjack/agents/test_specialist_agent.py +0 -4
- crackerjack/api.py +6 -25
- crackerjack/cli/cache_handlers.py +204 -0
- crackerjack/cli/cache_handlers_enhanced.py +683 -0
- crackerjack/cli/facade.py +100 -0
- crackerjack/cli/handlers.py +224 -9
- crackerjack/cli/interactive.py +6 -4
- crackerjack/cli/options.py +642 -55
- crackerjack/cli/utils.py +2 -1
- crackerjack/code_cleaner.py +58 -117
- crackerjack/config/global_lock_config.py +8 -48
- crackerjack/config/hooks.py +53 -62
- crackerjack/core/async_workflow_orchestrator.py +24 -34
- crackerjack/core/autofix_coordinator.py +3 -17
- crackerjack/core/enhanced_container.py +4 -13
- crackerjack/core/file_lifecycle.py +12 -89
- crackerjack/core/performance.py +2 -2
- crackerjack/core/performance_monitor.py +15 -55
- crackerjack/core/phase_coordinator.py +104 -204
- crackerjack/core/resource_manager.py +14 -90
- crackerjack/core/service_watchdog.py +62 -95
- crackerjack/core/session_coordinator.py +149 -0
- crackerjack/core/timeout_manager.py +14 -72
- crackerjack/core/websocket_lifecycle.py +13 -78
- crackerjack/core/workflow_orchestrator.py +171 -174
- crackerjack/docs/INDEX.md +11 -0
- crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
- crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
- crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
- crackerjack/docs/generated/api/SERVICES.md +1252 -0
- crackerjack/documentation/__init__.py +31 -0
- crackerjack/documentation/ai_templates.py +756 -0
- crackerjack/documentation/dual_output_generator.py +765 -0
- crackerjack/documentation/mkdocs_integration.py +518 -0
- crackerjack/documentation/reference_generator.py +977 -0
- crackerjack/dynamic_config.py +55 -50
- crackerjack/executors/async_hook_executor.py +10 -15
- crackerjack/executors/cached_hook_executor.py +117 -43
- crackerjack/executors/hook_executor.py +8 -34
- crackerjack/executors/hook_lock_manager.py +26 -183
- crackerjack/executors/individual_hook_executor.py +13 -11
- crackerjack/executors/lsp_aware_hook_executor.py +270 -0
- crackerjack/executors/tool_proxy.py +417 -0
- crackerjack/hooks/lsp_hook.py +79 -0
- crackerjack/intelligence/adaptive_learning.py +25 -10
- crackerjack/intelligence/agent_orchestrator.py +2 -5
- crackerjack/intelligence/agent_registry.py +34 -24
- crackerjack/intelligence/agent_selector.py +5 -7
- crackerjack/interactive.py +17 -6
- crackerjack/managers/async_hook_manager.py +0 -1
- crackerjack/managers/hook_manager.py +79 -1
- crackerjack/managers/publish_manager.py +44 -8
- crackerjack/managers/test_command_builder.py +1 -15
- crackerjack/managers/test_executor.py +1 -3
- crackerjack/managers/test_manager.py +98 -7
- crackerjack/managers/test_manager_backup.py +10 -9
- crackerjack/mcp/cache.py +2 -2
- crackerjack/mcp/client_runner.py +1 -1
- crackerjack/mcp/context.py +191 -68
- crackerjack/mcp/dashboard.py +7 -5
- crackerjack/mcp/enhanced_progress_monitor.py +31 -28
- crackerjack/mcp/file_monitor.py +30 -23
- crackerjack/mcp/progress_components.py +31 -21
- crackerjack/mcp/progress_monitor.py +50 -53
- crackerjack/mcp/rate_limiter.py +6 -6
- crackerjack/mcp/server_core.py +17 -16
- crackerjack/mcp/service_watchdog.py +2 -1
- crackerjack/mcp/state.py +4 -7
- crackerjack/mcp/task_manager.py +11 -9
- crackerjack/mcp/tools/core_tools.py +173 -32
- crackerjack/mcp/tools/error_analyzer.py +3 -2
- crackerjack/mcp/tools/execution_tools.py +8 -10
- crackerjack/mcp/tools/execution_tools_backup.py +42 -30
- crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
- crackerjack/mcp/tools/intelligence_tools.py +5 -2
- crackerjack/mcp/tools/monitoring_tools.py +33 -70
- crackerjack/mcp/tools/proactive_tools.py +24 -11
- crackerjack/mcp/tools/progress_tools.py +5 -8
- crackerjack/mcp/tools/utility_tools.py +20 -14
- crackerjack/mcp/tools/workflow_executor.py +62 -40
- crackerjack/mcp/websocket/app.py +8 -0
- crackerjack/mcp/websocket/endpoints.py +352 -357
- crackerjack/mcp/websocket/jobs.py +40 -57
- crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
- crackerjack/mcp/websocket/server.py +7 -25
- crackerjack/mcp/websocket/websocket_handler.py +6 -17
- crackerjack/mixins/__init__.py +0 -2
- crackerjack/mixins/error_handling.py +1 -70
- crackerjack/models/config.py +12 -1
- crackerjack/models/config_adapter.py +49 -1
- crackerjack/models/protocols.py +122 -122
- crackerjack/models/resource_protocols.py +55 -210
- crackerjack/monitoring/ai_agent_watchdog.py +13 -13
- crackerjack/monitoring/metrics_collector.py +426 -0
- crackerjack/monitoring/regression_prevention.py +8 -8
- crackerjack/monitoring/websocket_server.py +643 -0
- crackerjack/orchestration/advanced_orchestrator.py +11 -6
- crackerjack/orchestration/coverage_improvement.py +3 -3
- crackerjack/orchestration/execution_strategies.py +26 -6
- crackerjack/orchestration/test_progress_streamer.py +8 -5
- crackerjack/plugins/base.py +2 -2
- crackerjack/plugins/hooks.py +7 -0
- crackerjack/plugins/managers.py +11 -8
- crackerjack/security/__init__.py +0 -1
- crackerjack/security/audit.py +6 -35
- crackerjack/services/anomaly_detector.py +392 -0
- crackerjack/services/api_extractor.py +615 -0
- crackerjack/services/backup_service.py +2 -2
- crackerjack/services/bounded_status_operations.py +15 -152
- crackerjack/services/cache.py +127 -1
- crackerjack/services/changelog_automation.py +395 -0
- crackerjack/services/config.py +15 -9
- crackerjack/services/config_merge.py +19 -80
- crackerjack/services/config_template.py +506 -0
- crackerjack/services/contextual_ai_assistant.py +48 -22
- crackerjack/services/coverage_badge_service.py +171 -0
- crackerjack/services/coverage_ratchet.py +27 -25
- crackerjack/services/debug.py +3 -3
- crackerjack/services/dependency_analyzer.py +460 -0
- crackerjack/services/dependency_monitor.py +14 -11
- crackerjack/services/documentation_generator.py +491 -0
- crackerjack/services/documentation_service.py +675 -0
- crackerjack/services/enhanced_filesystem.py +6 -5
- crackerjack/services/enterprise_optimizer.py +865 -0
- crackerjack/services/error_pattern_analyzer.py +676 -0
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/git.py +8 -25
- crackerjack/services/health_metrics.py +10 -8
- crackerjack/services/heatmap_generator.py +735 -0
- crackerjack/services/initialization.py +11 -30
- crackerjack/services/input_validator.py +5 -97
- crackerjack/services/intelligent_commit.py +327 -0
- crackerjack/services/log_manager.py +15 -12
- crackerjack/services/logging.py +4 -3
- crackerjack/services/lsp_client.py +628 -0
- crackerjack/services/memory_optimizer.py +19 -87
- crackerjack/services/metrics.py +42 -33
- crackerjack/services/parallel_executor.py +9 -67
- crackerjack/services/pattern_cache.py +1 -1
- crackerjack/services/pattern_detector.py +6 -6
- crackerjack/services/performance_benchmarks.py +18 -59
- crackerjack/services/performance_cache.py +20 -81
- crackerjack/services/performance_monitor.py +27 -95
- crackerjack/services/predictive_analytics.py +510 -0
- crackerjack/services/quality_baseline.py +234 -0
- crackerjack/services/quality_baseline_enhanced.py +646 -0
- crackerjack/services/quality_intelligence.py +785 -0
- crackerjack/services/regex_patterns.py +605 -524
- crackerjack/services/regex_utils.py +43 -123
- crackerjack/services/secure_path_utils.py +5 -164
- crackerjack/services/secure_status_formatter.py +30 -141
- crackerjack/services/secure_subprocess.py +11 -92
- crackerjack/services/security.py +9 -41
- crackerjack/services/security_logger.py +12 -24
- crackerjack/services/server_manager.py +124 -16
- crackerjack/services/status_authentication.py +16 -159
- crackerjack/services/status_security_manager.py +4 -131
- crackerjack/services/thread_safe_status_collector.py +19 -125
- crackerjack/services/unified_config.py +21 -13
- crackerjack/services/validation_rate_limiter.py +5 -54
- crackerjack/services/version_analyzer.py +459 -0
- crackerjack/services/version_checker.py +1 -1
- crackerjack/services/websocket_resource_limiter.py +10 -144
- crackerjack/services/zuban_lsp_service.py +390 -0
- crackerjack/slash_commands/__init__.py +2 -7
- crackerjack/slash_commands/run.md +2 -2
- crackerjack/tools/validate_input_validator_patterns.py +14 -40
- crackerjack/tools/validate_regex_patterns.py +19 -48
- {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/METADATA +196 -25
- crackerjack-0.33.1.dist-info/RECORD +229 -0
- crackerjack/CLAUDE.md +0 -207
- crackerjack/RULES.md +0 -380
- crackerjack/py313.py +0 -234
- crackerjack-0.33.0.dist-info/RECORD +0 -187
- {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/WHEEL +0 -0
- {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.33.0.dist-info → crackerjack-0.33.1.dist-info}/licenses/LICENSE +0 -0
crackerjack/services/git.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import subprocess
|
|
2
|
+
import typing as t
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
from rich.console import Console
|
|
@@ -6,26 +7,23 @@ from rich.console import Console
|
|
|
6
7
|
from .secure_subprocess import execute_secure_subprocess
|
|
7
8
|
from .security_logger import get_security_logger
|
|
8
9
|
|
|
9
|
-
# Centralized Git command registry for security validation
|
|
10
10
|
GIT_COMMANDS = {
|
|
11
11
|
"git_dir": ["rev-parse", "--git-dir"],
|
|
12
12
|
"staged_files": ["diff", "--cached", "--name-only", "--diff-filter=ACMRT"],
|
|
13
13
|
"unstaged_files": ["diff", "--name-only", "--diff-filter=ACMRT"],
|
|
14
14
|
"untracked_files": ["ls-files", "--others", "--exclude-standard"],
|
|
15
15
|
"staged_files_simple": ["diff", "--cached", "--name-only"],
|
|
16
|
-
"add_file": ["add"],
|
|
16
|
+
"add_file": ["add"],
|
|
17
17
|
"add_all": ["add", "-A", "."],
|
|
18
|
-
"commit": ["commit", "-m"],
|
|
18
|
+
"commit": ["commit", "-m"],
|
|
19
19
|
"add_updated": ["add", "-u"],
|
|
20
20
|
"push_porcelain": ["push", "--porcelain"],
|
|
21
21
|
"current_branch": ["branch", "--show-current"],
|
|
22
|
-
"commits_ahead": ["rev-list", "--count", "@{u}..HEAD"],
|
|
22
|
+
"commits_ahead": ["rev-list[t.Any]", "--count", "@{u}..HEAD"],
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class FailedGitResult:
|
|
27
|
-
"""A Git result object compatible with subprocess.CompletedProcess."""
|
|
28
|
-
|
|
29
27
|
def __init__(self, command: list[str], error: str) -> None:
|
|
30
28
|
self.args = command
|
|
31
29
|
self.returncode = -1
|
|
@@ -41,7 +39,6 @@ class GitService:
|
|
|
41
39
|
def _run_git_command(
|
|
42
40
|
self, args: list[str]
|
|
43
41
|
) -> subprocess.CompletedProcess[str] | FailedGitResult:
|
|
44
|
-
"""Execute Git commands with secure subprocess validation."""
|
|
45
42
|
cmd = ["git", *args]
|
|
46
43
|
|
|
47
44
|
try:
|
|
@@ -51,10 +48,9 @@ class GitService:
|
|
|
51
48
|
capture_output=True,
|
|
52
49
|
text=True,
|
|
53
50
|
timeout=60,
|
|
54
|
-
check=False,
|
|
51
|
+
check=False,
|
|
55
52
|
)
|
|
56
53
|
except Exception as e:
|
|
57
|
-
# Log security issues but return a compatible result
|
|
58
54
|
security_logger = get_security_logger()
|
|
59
55
|
security_logger.log_subprocess_failure(
|
|
60
56
|
command=cmd,
|
|
@@ -62,7 +58,6 @@ class GitService:
|
|
|
62
58
|
error_output=str(e),
|
|
63
59
|
)
|
|
64
60
|
|
|
65
|
-
# Create compatible result for Git operations
|
|
66
61
|
return FailedGitResult(cmd, str(e))
|
|
67
62
|
|
|
68
63
|
def is_git_repo(self) -> bool:
|
|
@@ -95,7 +90,7 @@ class GitService:
|
|
|
95
90
|
else []
|
|
96
91
|
)
|
|
97
92
|
|
|
98
|
-
all_files = set(staged_files + unstaged_files + untracked_files)
|
|
93
|
+
all_files = set[t.Any](staged_files + unstaged_files + untracked_files)
|
|
99
94
|
return [f for f in all_files if f]
|
|
100
95
|
except Exception as e:
|
|
101
96
|
self.console.print(f"[yellow]⚠️[/ yellow] Error getting changed files: {e}")
|
|
@@ -125,7 +120,6 @@ class GitService:
|
|
|
125
120
|
return False
|
|
126
121
|
|
|
127
122
|
def add_all_files(self) -> bool:
|
|
128
|
-
"""Stage all changes including new, modified, and deleted files."""
|
|
129
123
|
try:
|
|
130
124
|
result = self._run_git_command(GIT_COMMANDS["add_all"])
|
|
131
125
|
if result.returncode == 0:
|
|
@@ -200,7 +194,6 @@ class GitService:
|
|
|
200
194
|
|
|
201
195
|
def push(self) -> bool:
|
|
202
196
|
try:
|
|
203
|
-
# Get detailed push information
|
|
204
197
|
result = self._run_git_command(GIT_COMMANDS["push_porcelain"])
|
|
205
198
|
if result.returncode == 0:
|
|
206
199
|
self._display_push_success(result.stdout)
|
|
@@ -212,7 +205,6 @@ class GitService:
|
|
|
212
205
|
return False
|
|
213
206
|
|
|
214
207
|
def _display_push_success(self, push_output: str) -> None:
|
|
215
|
-
"""Display detailed push success information."""
|
|
216
208
|
lines = push_output.strip().split("\n") if push_output.strip() else []
|
|
217
209
|
|
|
218
210
|
if not lines:
|
|
@@ -223,15 +215,12 @@ class GitService:
|
|
|
223
215
|
self._display_push_results(pushed_refs)
|
|
224
216
|
|
|
225
217
|
def _display_no_commits_message(self) -> None:
|
|
226
|
-
"""Display message for no new commits."""
|
|
227
218
|
self.console.print("[green]✅[/ green] Pushed to remote (no new commits)")
|
|
228
219
|
|
|
229
220
|
def _parse_pushed_refs(self, lines: list[str]) -> list[str]:
|
|
230
|
-
"""Parse pushed references from git output."""
|
|
231
221
|
pushed_refs = []
|
|
232
222
|
for line in lines:
|
|
233
223
|
if line.startswith(("*", "+", "=")):
|
|
234
|
-
# Parse porcelain output: flag:from:to summary
|
|
235
224
|
parts = line.split("\t")
|
|
236
225
|
if len(parts) >= 2:
|
|
237
226
|
summary = parts[1] if len(parts) > 1 else ""
|
|
@@ -239,21 +228,17 @@ class GitService:
|
|
|
239
228
|
return pushed_refs
|
|
240
229
|
|
|
241
230
|
def _display_push_results(self, pushed_refs: list[str]) -> None:
|
|
242
|
-
"""Display the push results to console."""
|
|
243
231
|
if pushed_refs:
|
|
244
232
|
self.console.print(
|
|
245
|
-
f"[green]✅[/ green] Successfully pushed {len(pushed_refs)} ref(s) to remote:"
|
|
233
|
+
f"[green]✅[/ green] Successfully pushed {len(pushed_refs)} ref(s) to remote: "
|
|
246
234
|
)
|
|
247
235
|
for ref in pushed_refs:
|
|
248
|
-
self.console.print(f"
|
|
236
|
+
self.console.print(f" [dim]→ {ref}[/ dim]")
|
|
249
237
|
else:
|
|
250
|
-
# Get commit count as fallback
|
|
251
238
|
self._display_commit_count_push()
|
|
252
239
|
|
|
253
240
|
def _display_commit_count_push(self) -> None:
|
|
254
|
-
"""Fallback method to show commit count information."""
|
|
255
241
|
try:
|
|
256
|
-
# Get commits ahead of remote
|
|
257
242
|
result = self._run_git_command(GIT_COMMANDS["commits_ahead"])
|
|
258
243
|
if result.returncode == 0 and result.stdout.strip().isdigit():
|
|
259
244
|
commit_count = int(result.stdout.strip())
|
|
@@ -266,7 +251,6 @@ class GitService:
|
|
|
266
251
|
"[green]✅[/ green] Pushed to remote (up to date)"
|
|
267
252
|
)
|
|
268
253
|
else:
|
|
269
|
-
# Even more basic fallback
|
|
270
254
|
self.console.print("[green]✅[/ green] Successfully pushed to remote")
|
|
271
255
|
except (ValueError, Exception):
|
|
272
256
|
self.console.print("[green]✅[/ green] Successfully pushed to remote")
|
|
@@ -335,7 +319,6 @@ class GitService:
|
|
|
335
319
|
return messages
|
|
336
320
|
|
|
337
321
|
def get_unpushed_commit_count(self) -> int:
|
|
338
|
-
"""Get the number of unpushed commits."""
|
|
339
322
|
from contextlib import suppress
|
|
340
323
|
|
|
341
324
|
with suppress(ValueError, Exception):
|
|
@@ -9,6 +9,7 @@ from datetime import datetime
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
import requests
|
|
12
13
|
from rich.console import Console
|
|
13
14
|
|
|
14
15
|
from crackerjack.models.protocols import FileSystemInterface
|
|
@@ -18,7 +19,7 @@ from crackerjack.models.protocols import FileSystemInterface
|
|
|
18
19
|
class ProjectHealth:
|
|
19
20
|
lint_error_trend: list[int] = field(default_factory=list)
|
|
20
21
|
test_coverage_trend: list[float] = field(default_factory=list)
|
|
21
|
-
dependency_age: dict[str, int] = field(default_factory=dict)
|
|
22
|
+
dependency_age: dict[str, int] = field(default_factory=dict[str, t.Any])
|
|
22
23
|
config_completeness: float = 0.0
|
|
23
24
|
last_updated: float = field(default_factory=time.time)
|
|
24
25
|
|
|
@@ -344,14 +345,13 @@ class HealthMetricsService:
|
|
|
344
345
|
|
|
345
346
|
def _fetch_package_data(self, package_name: str) -> dict[str, t.Any] | None:
|
|
346
347
|
try:
|
|
347
|
-
import urllib.request
|
|
348
348
|
from urllib.parse import urlparse
|
|
349
349
|
|
|
350
|
-
url = f"https
|
|
350
|
+
url = f"https: //pypi.org/pypi/{package_name}/json"
|
|
351
351
|
|
|
352
352
|
parsed = urlparse(url)
|
|
353
353
|
if parsed.scheme != "https" or parsed.netloc != "pypi.org":
|
|
354
|
-
msg = f"Invalid URL: only https
|
|
354
|
+
msg = f"Invalid URL: only https: //pypi.org URLs are allowed, got {url}"
|
|
355
355
|
raise ValueError(msg)
|
|
356
356
|
|
|
357
357
|
if not parsed.path.startswith("/pypi/") or not parsed.path.endswith(
|
|
@@ -360,9 +360,10 @@ class HealthMetricsService:
|
|
|
360
360
|
msg = f"Invalid PyPI API path: {parsed.path}"
|
|
361
361
|
raise ValueError(msg)
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
363
|
+
response = requests.get(url, timeout=10, verify=True)
|
|
364
|
+
response.raise_for_status()
|
|
365
|
+
json_result = response.json()
|
|
366
|
+
return t.cast(dict[str, t.Any] | None, json_result)
|
|
366
367
|
except Exception:
|
|
367
368
|
return None
|
|
368
369
|
|
|
@@ -378,7 +379,8 @@ class HealthMetricsService:
|
|
|
378
379
|
if not release_info:
|
|
379
380
|
return None
|
|
380
381
|
|
|
381
|
-
|
|
382
|
+
upload_time_raw = release_info[0].get("upload_time", "")
|
|
383
|
+
return t.cast(str | None, upload_time_raw)
|
|
382
384
|
|
|
383
385
|
def _calculate_days_since_upload(self, upload_time: str) -> int | None:
|
|
384
386
|
try:
|