crackerjack 0.38.11__py3-none-any.whl → 0.38.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/__main__.py CHANGED
@@ -1318,7 +1318,6 @@ def main(
1318
1318
  config_interactive: bool = CLI_OPTIONS["config_interactive"],
1319
1319
  refresh_cache: bool = CLI_OPTIONS["refresh_cache"],
1320
1320
  ) -> None:
1321
- """Main CLI entry point with complexity <= 15."""
1322
1321
  options = create_options(
1323
1322
  commit,
1324
1323
  interactive,
@@ -261,11 +261,11 @@ class SmartCacheManager:
261
261
  hook_name: str,
262
262
  project_state: dict[str, t.Any],
263
263
  ) -> bool:
264
- external_hooks = {"detect-secrets"}
264
+ external_hooks = set()
265
265
  if hook_name in external_hooks:
266
266
  return False
267
267
 
268
- expensive_hooks = {"pyright", "bandit", "vulture", "complexipy"}
268
+ expensive_hooks = {"pyright", "bandit", "vulture", "complexipy", "gitleaks"}
269
269
  if hook_name in expensive_hooks:
270
270
  return True
271
271
 
@@ -198,7 +198,7 @@ class StrategySelector:
198
198
  if "test" in str(file_path):
199
199
  priority_hooks.update(["pytest", "coverage"])
200
200
  if str(file_path).endswith(("setup.py", "pyproject.toml")):
201
- priority_hooks.update(["bandit", "creosote", "detect-secrets"])
201
+ priority_hooks.update(["bandit", "creosote", "gitleaks"])
202
202
 
203
203
  selected_hooks = [
204
204
  hook for hook in strategy.hooks if hook.name in priority_hooks
crackerjack/py313.py ADDED
@@ -0,0 +1,189 @@
1
+ import subprocess
2
+ import typing
3
+ from enum import Enum, auto
4
+ from pathlib import Path
5
+ from typing import Any, Self, TypedDict
6
+
7
+
8
+ class CommandRunner[TReturn]:
9
+ def run_command(self, cmd: list[str], **kwargs: Any) -> TReturn:
10
+ raise NotImplementedError("Subclasses must implement run_command")
11
+
12
+
13
+ class CommandResult(TypedDict):
14
+ success: bool
15
+ exit_code: int
16
+ stdout: str
17
+ stderr: str
18
+ command: list[str]
19
+ duration_ms: float
20
+
21
+
22
+ def process_command_output(result: CommandResult) -> tuple[bool, str]:
23
+ match result:
24
+ case {"success": True, "stdout": stdout} if stdout.strip():
25
+ return (True, stdout)
26
+ case {"success": True}:
27
+ return (True, "Command completed successfully with no output")
28
+ case {"success": False, "exit_code": code, "stderr": stderr} if code == 127:
29
+ return (False, f"Command not found: {stderr}")
30
+ case {"success": False, "exit_code": code} if code > 0:
31
+ return (False, f"Command failed with exit code {code}: {result['stderr']}")
32
+ case _:
33
+ pass
34
+ return (False, "Unknown command result pattern")
35
+
36
+
37
+ class HookStatus(Enum):
38
+ SUCCESS = auto()
39
+ FAILURE = auto()
40
+ SKIPPED = auto()
41
+ ERROR = auto()
42
+
43
+
44
+ class HookResult(TypedDict):
45
+ status: HookStatus
46
+ hook_id: str
47
+ output: str
48
+ files: list[str]
49
+
50
+
51
+ def analyze_hook_result(result: HookResult) -> str:
52
+ match result:
53
+ case {"status": HookStatus.SUCCESS, "hook_id": hook_id}:
54
+ return f"✅ Hook {hook_id} passed successfully"
55
+ case {"status": HookStatus.FAILURE, "hook_id": hook_id, "output": output} if (
56
+ "fixable" in output
57
+ ):
58
+ return f"🔧 Hook {hook_id} failed with fixable issues"
59
+ case {"status": HookStatus.FAILURE, "hook_id": hook_id}:
60
+ return f"❌ Hook {hook_id} failed"
61
+ case {"status": HookStatus.SKIPPED, "hook_id": hook_id}:
62
+ return f"⏩ Hook {hook_id} was skipped"
63
+ case {"status": HookStatus.ERROR, "hook_id": hook_id, "output": output}:
64
+ return f"💥 Hook {hook_id} encountered an error: {output}"
65
+ case _:
66
+ pass
67
+ return "Unknown hook result pattern"
68
+
69
+
70
+ class ModernConfigManager:
71
+ def __init__(self, config_path: Path) -> None:
72
+ self.config_path = config_path
73
+ self.config: dict[str, Any] = {}
74
+
75
+ def load(self) -> Self:
76
+ return self
77
+
78
+ def update(self, key: str, value: Any) -> Self:
79
+ self.config[key] = value
80
+ return self
81
+
82
+ def save(self) -> Self:
83
+ return self
84
+
85
+
86
+ def categorize_file(file_path: Path) -> str:
87
+ path_str = str(file_path)
88
+ name = file_path
89
+ match path_str:
90
+ case s if name.suffix == ".py" and "/ tests /" in s:
91
+ return "Python Test File"
92
+ case s if name.suffix == ".py" and "__init__.py" in name.name:
93
+ return "Python Module Init"
94
+ case s if name.suffix == ".py":
95
+ return "Python Source File"
96
+ case s if name.suffix in {".md", ".rst", ".txt"}:
97
+ return "Documentation File"
98
+ case s if name.stem.startswith(".") or name.name in {
99
+ ".gitignore",
100
+ ".pre-commit-config.yaml",
101
+ }:
102
+ return "Configuration File"
103
+ case _:
104
+ pass
105
+ return "Unknown File Type"
106
+
107
+
108
+ def process_hook_results[T: HookResult, R](
109
+ results: list[T],
110
+ success_handler: typing.Callable[[T], R],
111
+ failure_handler: typing.Callable[[T], R],
112
+ ) -> list[R]:
113
+ processed_results: list[R] = []
114
+ for result in results:
115
+ # Type checker knows T is HookResult, so no need for isinstance check
116
+ # But we keep it for runtime safety
117
+ if hasattr(result, "status") and result.status == HookStatus.SUCCESS:
118
+ processed_results.append(success_handler(result))
119
+ else:
120
+ processed_results.append(failure_handler(result))
121
+ return processed_results
122
+
123
+
124
+ class EnhancedCommandRunner:
125
+ def __init__(self, working_dir: Path | None = None) -> None:
126
+ self.working_dir = working_dir
127
+
128
+ def run(self, cmd: list[str], **kwargs: Any) -> CommandResult:
129
+ import time
130
+
131
+ start_time = time.time()
132
+ try:
133
+ process = subprocess.run(
134
+ cmd,
135
+ check=False,
136
+ capture_output=True,
137
+ text=True,
138
+ cwd=self.working_dir,
139
+ **kwargs,
140
+ )
141
+ duration_ms = (time.time() - start_time) * 1000
142
+ return CommandResult(
143
+ success=process.returncode == 0,
144
+ exit_code=process.returncode,
145
+ stdout=process.stdout,
146
+ stderr=process.stderr,
147
+ command=cmd,
148
+ duration_ms=duration_ms,
149
+ )
150
+ except subprocess.SubprocessError as e:
151
+ duration_ms = (time.time() - start_time) * 1000
152
+ return CommandResult(
153
+ success=False,
154
+ exit_code=-1,
155
+ stdout="",
156
+ stderr=str(e),
157
+ command=cmd,
158
+ duration_ms=duration_ms,
159
+ )
160
+
161
+ def handle_result(self, result: CommandResult) -> tuple[bool, str]:
162
+ return process_command_output(result)
163
+
164
+
165
+ def clean_python_code(code: str) -> str:
166
+ lines = code.splitlines()
167
+ cleaned_lines: list[str] = []
168
+ for line in lines:
169
+ match line.strip():
170
+ case "":
171
+ if not cleaned_lines or cleaned_lines[-1].strip():
172
+ cleaned_lines.append("")
173
+ case s if s.startswith(("import ", "from ")):
174
+ cleaned_lines.append(line)
175
+ case s if s.startswith("#"):
176
+ continue
177
+ case s if "#" in s and (
178
+ not any(
179
+ skip in s for skip in ("# noqa", "# type: ", "# pragma", "# skip")
180
+ )
181
+ ):
182
+ code_part = line.split("#", 1)[0].rstrip()
183
+ if code_part:
184
+ cleaned_lines.append(code_part)
185
+ case s if s.startswith(('"""', "'''")):
186
+ continue
187
+ case _:
188
+ cleaned_lines.append(line)
189
+ return "\n".join(cleaned_lines)
@@ -228,7 +228,6 @@ class CrackerjackCache:
228
228
  "complexipy",
229
229
  "refurb",
230
230
  "gitleaks",
231
- "detect-secrets",
232
231
  }
233
232
 
234
233
  # TTL configuration for different cache types (in seconds)
@@ -239,7 +238,6 @@ class CrackerjackCache:
239
238
  "complexipy": 86400, # 24 hours - complexity analysis
240
239
  "refurb": 86400, # 24 hours - code improvements
241
240
  "gitleaks": 86400 * 7, # 7 days - secret detection is very stable
242
- "detect-secrets": 86400 * 7, # 7 days - secret detection
243
241
  }
244
242
 
245
243
  # Agent version for cache invalidation when agent logic changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crackerjack
3
- Version: 0.38.11
3
+ Version: 0.38.13
4
4
  Summary: Crackerjack Python project management tool
5
5
  Project-URL: documentation, https://github.com/lesleslie/crackerjack
6
6
  Project-URL: homepage, https://github.com/lesleslie/crackerjack
@@ -1,11 +1,12 @@
1
1
  crackerjack/CLAUDE.md,sha256=FnF1XgcaCB59HEZxglEl4qEBTMyHQcqKoL0YjnAq24s,41230
2
2
  crackerjack/__init__.py,sha256=DajG9zHB8qBdgdiKMumrrssUbKeMXmtIQ3oOaSTb46Y,1426
3
- crackerjack/__main__.py,sha256=hOekfMkVBYQuw294OHa8fhpuQa-E8knJh3x4KY1WxG8,55552
3
+ crackerjack/__main__.py,sha256=6Te0CW6qyKiso0cTHv9stWnDZ9W8KnWXzW0oQ3hN7n8,55498
4
4
  crackerjack/api.py,sha256=PyCRaZHvKWdu62_2O4t_HcEfKNBdqyrfPdonS_PNn4c,21495
5
5
  crackerjack/code_cleaner.py,sha256=M1zVaq31uW0nOkPneKR8kfR3892gyyVx0VhFgRaxsj4,44338
6
6
  crackerjack/dynamic_config.py,sha256=4c8Fts9vyH8Tdon_47OFVT1iTBINSzSgB0WoeSvpzII,22418
7
7
  crackerjack/errors.py,sha256=yYbZ92kn_y6acEWgQvEPvozAYs2HT65uLwAXrtXxGsE,10049
8
8
  crackerjack/interactive.py,sha256=t5FbxWeOErSl5kod4V8Gu5yF5yuWoZlwqlOdquOQ-vo,21943
9
+ crackerjack/py313.py,sha256=uLzXnII2N3Qng45lzb8-gMVe3z-U9dmT7V_BRV-zHJo,6192
9
10
  crackerjack/adapters/__init__.py,sha256=k-8ajMDL9DS9hV2FYOu694nmNQg3HkudJRuNcXmx8N4,451
10
11
  crackerjack/adapters/lsp_client.py,sha256=4kQ3T5JiWC7uc6kOjZuPdtUboseKSDjZpuKQpV74onc,10963
11
12
  crackerjack/adapters/rust_tool_adapter.py,sha256=ui_qMt_WIwInRvRCeT7MnIdp8eln7Fvp4hakXQiVnjg,5999
@@ -69,7 +70,7 @@ crackerjack/documentation/mkdocs_integration.py,sha256=KqU2_9mA-rjP_VDrrfr6KTuPW
69
70
  crackerjack/documentation/reference_generator.py,sha256=NGAIsC5bnjLBQkvEXPDU0pw8bQ5kYzbUUokhlXXFqrU,34520
70
71
  crackerjack/executors/__init__.py,sha256=HF-DmXvKN45uKKDdiMxOT9bYxuy1B-Z91BihOhkK5lg,322
71
72
  crackerjack/executors/async_hook_executor.py,sha256=FmKpiAxpZXKwvOWXnRQ73N-reDfX8NusESQ9a4HeacM,17620
72
- crackerjack/executors/cached_hook_executor.py,sha256=izwdW0B22EZcl_2_llmTIyq5oTcZDZTRL2G97ZwYiXg,11173
73
+ crackerjack/executors/cached_hook_executor.py,sha256=MwnHHBk6KJ_ovAJvAkVA-ad6D2cE0EgXNwy-NZQqB18,11172
73
74
  crackerjack/executors/hook_executor.py,sha256=g53TXs5hOY0yRnSpyr44GgEmCRPMxHRgkfjtqBx_-4s,14479
74
75
  crackerjack/executors/hook_lock_manager.py,sha256=ft24q6VFEkW_QrifNnSlrQeHGx9GuJeOOTsdlCcjnMI,26694
75
76
  crackerjack/executors/individual_hook_executor.py,sha256=t0W9vuqLGPx0HmbTo01N9MRFyqLfY0ZLG06ZIA5qfBY,24362
@@ -142,7 +143,7 @@ crackerjack/monitoring/websocket_server.py,sha256=tmCYh5Qp58iicS_txj5OTdmt3I85M5
142
143
  crackerjack/orchestration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
144
  crackerjack/orchestration/advanced_orchestrator.py,sha256=05AZhCkPIiKSVVpIx7gb2_wVvGAKHv7gStu146ivcmY,32066
144
145
  crackerjack/orchestration/coverage_improvement.py,sha256=XUTUcgub0nP3vvQ8Ud5SmCYKgulEe8SAY65jbcFQzdw,6869
145
- crackerjack/orchestration/execution_strategies.py,sha256=M3hplgaCULMwE9TiqP9rWvivnrqdSR6DJTzY_rvueww,12482
146
+ crackerjack/orchestration/execution_strategies.py,sha256=Iq5Q-dwC2GQ5E99kawqet031DnsrQCxSrqzTPnoWDbE,12476
146
147
  crackerjack/orchestration/test_progress_streamer.py,sha256=Yu6uHuhoCvX6SZP0QNG3Yt8Q4s2tufEHr40o16QU98c,22541
147
148
  crackerjack/plugins/__init__.py,sha256=B7hy9b9amJVbYLHgIz8kgTI29j-vYxsUY_sZ5ISbXU0,386
148
149
  crackerjack/plugins/base.py,sha256=VFk-xNsgjSlmzJ_iPQALhkr7cguiOtEd3XSR9CcCPkc,5732
@@ -156,7 +157,7 @@ crackerjack/services/anomaly_detector.py,sha256=vUwhhGxNGarHQAly4GaN7kc5PBaBvlTf
156
157
  crackerjack/services/api_extractor.py,sha256=iN4JDkvSyfHRNlhgV0Sf5B9cg4NVaCZn6p-zQlp9YGU,23836
157
158
  crackerjack/services/backup_service.py,sha256=0e8AAo9svSBtbsbI9vwnAVSilB2fjph61lskgsUvDLk,15528
158
159
  crackerjack/services/bounded_status_operations.py,sha256=mrBkUQwgtYjkbp-Y-5MdrU2A3rp3ZLVgOJv9vLdnJ8k,18763
159
- crackerjack/services/cache.py,sha256=FutQKxItKSdQFzOlWQaQzVBEfn6lbPXCDdvNnz3NCDQ,14536
160
+ crackerjack/services/cache.py,sha256=ZNpIHPoslMxgwfqzKJQQEqGUVlar22KGDQbydDuqx-M,14444
160
161
  crackerjack/services/changelog_automation.py,sha256=KUeXCYLihRfLR0mUIRiI2aRQdCfe-45GnbB2gYNJJQE,14095
161
162
  crackerjack/services/config.py,sha256=1gUQkcHPCGHVYSlx6mcrJlJLVIWhdaL7RjEmuy8_ev4,13704
162
163
  crackerjack/services/config_integrity.py,sha256=Ac6-c7WuupsyrP2dxx_ijgjzpNnx9G0NWsXB-SZjelg,2904
@@ -225,8 +226,8 @@ crackerjack/tools/validate_input_validator_patterns.py,sha256=NN7smYlXWrHLQXTb-8
225
226
  crackerjack/tools/validate_regex_patterns.py,sha256=J7GG9EP1fASpRIsG8qRPeiCSkdCwmk0sdo29GgoJ6w8,5863
226
227
  crackerjack/ui/__init__.py,sha256=eMb1OeTU-dSLICAACn0YdYB4Amdr8wHckjKfn0wOIZE,37
227
228
  crackerjack/ui/server_panels.py,sha256=F5IH6SNN06BaZQMsFx_D-OA286aojmaFPJ5kvvSRv_c,4232
228
- crackerjack-0.38.11.dist-info/METADATA,sha256=zlNpnIwM-e0waeO6GFqQpCowVWE4inrrE05ZSCdDk64,38083
229
- crackerjack-0.38.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
230
- crackerjack-0.38.11.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
231
- crackerjack-0.38.11.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
232
- crackerjack-0.38.11.dist-info/RECORD,,
229
+ crackerjack-0.38.13.dist-info/METADATA,sha256=0Hn2s62A3z7OJwd0jlZ67DDRblFHWPSNXLbhYfWq9HE,38083
230
+ crackerjack-0.38.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
231
+ crackerjack-0.38.13.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
232
+ crackerjack-0.38.13.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
233
+ crackerjack-0.38.13.dist-info/RECORD,,