crackerjack 0.21.5__py3-none-any.whl → 0.21.7__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.
- crackerjack/.gitignore +4 -1
- crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
- crackerjack/__init__.py +0 -1
- crackerjack/__main__.py +0 -1
- crackerjack/crackerjack.py +100 -46
- crackerjack/errors.py +0 -1
- crackerjack/interactive.py +0 -10
- crackerjack/pyproject.toml +1 -1
- {crackerjack-0.21.5.dist-info → crackerjack-0.21.7.dist-info}/METADATA +8 -8
- {crackerjack-0.21.5.dist-info → crackerjack-0.21.7.dist-info}/RECORD +13 -13
- {crackerjack-0.21.5.dist-info → crackerjack-0.21.7.dist-info}/WHEEL +0 -0
- {crackerjack-0.21.5.dist-info → crackerjack-0.21.7.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.21.5.dist-info → crackerjack-0.21.7.dist-info}/licenses/LICENSE +0 -0
crackerjack/.gitignore
CHANGED
Binary file
|
crackerjack/__init__.py
CHANGED
crackerjack/__main__.py
CHANGED
crackerjack/crackerjack.py
CHANGED
@@ -6,7 +6,6 @@ from pathlib import Path
|
|
6
6
|
from subprocess import CompletedProcess
|
7
7
|
from subprocess import run as execute
|
8
8
|
from tomllib import loads
|
9
|
-
|
10
9
|
from pydantic import BaseModel
|
11
10
|
from rich.console import Console
|
12
11
|
from tomli_w import dumps
|
@@ -86,28 +85,93 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
86
85
|
except Exception as e:
|
87
86
|
print(f"Error cleaning {file_path}: {e}")
|
88
87
|
|
88
|
+
def _initialize_docstring_state(self) -> dict[str, t.Any]:
|
89
|
+
return {
|
90
|
+
"in_docstring": False,
|
91
|
+
"delimiter": None,
|
92
|
+
"waiting": False,
|
93
|
+
"function_indent": 0,
|
94
|
+
"removed_docstring": False,
|
95
|
+
"in_multiline_def": False,
|
96
|
+
}
|
97
|
+
|
98
|
+
def _handle_function_definition(
|
99
|
+
self, line: str, stripped: str, state: dict[str, t.Any]
|
100
|
+
) -> bool:
|
101
|
+
if self._is_function_or_class_definition(stripped):
|
102
|
+
state["waiting"] = True
|
103
|
+
state["function_indent"] = len(line) - len(line.lstrip())
|
104
|
+
state["removed_docstring"] = False
|
105
|
+
state["in_multiline_def"] = not stripped.endswith(":")
|
106
|
+
return True
|
107
|
+
return False
|
108
|
+
|
109
|
+
def _handle_multiline_definition(
|
110
|
+
self, line: str, stripped: str, state: dict[str, t.Any]
|
111
|
+
) -> bool:
|
112
|
+
if state["in_multiline_def"]:
|
113
|
+
if stripped.endswith(":"):
|
114
|
+
state["in_multiline_def"] = False
|
115
|
+
return True
|
116
|
+
return False
|
117
|
+
|
118
|
+
def _handle_waiting_docstring(
|
119
|
+
self, lines: list[str], i: int, stripped: str, state: dict[str, t.Any]
|
120
|
+
) -> tuple[bool, str | None]:
|
121
|
+
if state["waiting"] and stripped:
|
122
|
+
if self._handle_docstring_start(stripped, state):
|
123
|
+
pass_line = None
|
124
|
+
if not state["in_docstring"]:
|
125
|
+
function_indent: int = state["function_indent"]
|
126
|
+
if self._needs_pass_statement(lines, i + 1, function_indent):
|
127
|
+
pass_line = " " * (function_indent + 4) + "pass"
|
128
|
+
state["removed_docstring"] = True
|
129
|
+
return True, pass_line
|
130
|
+
else:
|
131
|
+
state["waiting"] = False
|
132
|
+
return False, None
|
133
|
+
|
134
|
+
def _handle_docstring_content(
|
135
|
+
self, lines: list[str], i: int, stripped: str, state: dict[str, t.Any]
|
136
|
+
) -> tuple[bool, str | None]:
|
137
|
+
if state["in_docstring"]:
|
138
|
+
if self._handle_docstring_end(stripped, state):
|
139
|
+
pass_line = None
|
140
|
+
function_indent: int = state["function_indent"]
|
141
|
+
if self._needs_pass_statement(lines, i + 1, function_indent):
|
142
|
+
pass_line = " " * (function_indent + 4) + "pass"
|
143
|
+
state["removed_docstring"] = False
|
144
|
+
return True, pass_line
|
145
|
+
else:
|
146
|
+
return True, None
|
147
|
+
return False, None
|
148
|
+
|
149
|
+
def _process_line(
|
150
|
+
self, lines: list[str], i: int, line: str, state: dict[str, t.Any]
|
151
|
+
) -> tuple[bool, str | None]:
|
152
|
+
stripped = line.strip()
|
153
|
+
if self._handle_function_definition(line, stripped, state):
|
154
|
+
return True, line
|
155
|
+
if self._handle_multiline_definition(line, stripped, state):
|
156
|
+
return True, line
|
157
|
+
handled, pass_line = self._handle_waiting_docstring(lines, i, stripped, state)
|
158
|
+
if handled:
|
159
|
+
return True, pass_line
|
160
|
+
handled, pass_line = self._handle_docstring_content(lines, i, stripped, state)
|
161
|
+
if handled:
|
162
|
+
return True, pass_line
|
163
|
+
if state["removed_docstring"] and stripped:
|
164
|
+
state["removed_docstring"] = False
|
165
|
+
return False, line
|
166
|
+
|
89
167
|
def remove_docstrings(self, code: str) -> str:
|
90
168
|
lines = code.split("\n")
|
91
169
|
cleaned_lines = []
|
92
|
-
docstring_state =
|
93
|
-
for line in lines:
|
94
|
-
|
95
|
-
if
|
96
|
-
|
97
|
-
cleaned_lines.append(line)
|
98
|
-
continue
|
99
|
-
if docstring_state["waiting"] and stripped:
|
100
|
-
if self._handle_docstring_start(stripped, docstring_state):
|
101
|
-
continue
|
102
|
-
else:
|
103
|
-
docstring_state["waiting"] = False
|
104
|
-
if docstring_state["in_docstring"]:
|
105
|
-
if self._handle_docstring_end(stripped, docstring_state):
|
106
|
-
continue
|
107
|
-
else:
|
108
|
-
continue
|
109
|
-
cleaned_lines.append(line)
|
110
|
-
|
170
|
+
docstring_state = self._initialize_docstring_state()
|
171
|
+
for i, line in enumerate(lines):
|
172
|
+
_, result_line = self._process_line(lines, i, line, docstring_state)
|
173
|
+
if result_line:
|
174
|
+
cleaned_lines.append(result_line)
|
111
175
|
return "\n".join(cleaned_lines)
|
112
176
|
|
113
177
|
def _is_function_or_class_definition(self, stripped_line: str) -> bool:
|
@@ -137,6 +201,21 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
137
201
|
state["in_docstring"] = False
|
138
202
|
state["delimiter"] = None
|
139
203
|
return True
|
204
|
+
return False
|
205
|
+
|
206
|
+
def _needs_pass_statement(
|
207
|
+
self, lines: list[str], start_index: int, function_indent: int
|
208
|
+
) -> bool:
|
209
|
+
for i in range(start_index, len(lines)):
|
210
|
+
line = lines[i]
|
211
|
+
stripped = line.strip()
|
212
|
+
if not stripped:
|
213
|
+
continue
|
214
|
+
line_indent = len(line) - len(line.lstrip())
|
215
|
+
if line_indent <= function_indent:
|
216
|
+
return True
|
217
|
+
if line_indent > function_indent:
|
218
|
+
return False
|
140
219
|
return True
|
141
220
|
|
142
221
|
def remove_line_comments(self, code: str) -> str:
|
@@ -149,7 +228,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
149
228
|
cleaned_line = self._process_line_for_comments(line)
|
150
229
|
if cleaned_line or not line.strip():
|
151
230
|
cleaned_lines.append(cleaned_line or line)
|
152
|
-
|
153
231
|
return "\n".join(cleaned_lines)
|
154
232
|
|
155
233
|
def _process_line_for_comments(self, line: str) -> str:
|
@@ -162,7 +240,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
162
240
|
break
|
163
241
|
else:
|
164
242
|
result.append(char)
|
165
|
-
|
166
243
|
return "".join(result).rstrip()
|
167
244
|
|
168
245
|
def _handle_string_character(
|
@@ -173,18 +250,14 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
173
250
|
string_state: dict[str, t.Any],
|
174
251
|
result: list[str],
|
175
252
|
) -> bool:
|
176
|
-
"""Handle string quote characters. Returns True if character was handled."""
|
177
253
|
if char not in ("'", '"'):
|
178
254
|
return False
|
179
|
-
|
180
255
|
if index > 0 and line[index - 1] == "\\":
|
181
256
|
return False
|
182
|
-
|
183
257
|
if string_state["in_string"] is None:
|
184
258
|
string_state["in_string"] = char
|
185
259
|
elif string_state["in_string"] == char:
|
186
260
|
string_state["in_string"] = None
|
187
|
-
|
188
261
|
result.append(char)
|
189
262
|
return True
|
190
263
|
|
@@ -196,14 +269,11 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
196
269
|
string_state: dict[str, t.Any],
|
197
270
|
result: list[str],
|
198
271
|
) -> bool:
|
199
|
-
"""Handle comment character. Returns True if comment was found."""
|
200
272
|
if char != "#" or string_state["in_string"] is not None:
|
201
273
|
return False
|
202
|
-
|
203
274
|
comment = line[index:].strip()
|
204
275
|
if self._is_special_comment_line(comment):
|
205
276
|
result.append(line[index:])
|
206
|
-
|
207
277
|
return True
|
208
278
|
|
209
279
|
def _is_special_comment_line(self, comment: str) -> bool:
|
@@ -227,13 +297,11 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
227
297
|
):
|
228
298
|
continue
|
229
299
|
cleaned_lines.append(line)
|
230
|
-
|
231
300
|
return "\n".join(self._remove_trailing_empty_lines(cleaned_lines))
|
232
301
|
|
233
302
|
def _update_function_state(
|
234
303
|
self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
|
235
304
|
) -> None:
|
236
|
-
"""Update function tracking state based on current line."""
|
237
305
|
if stripped_line.startswith(("def ", "async def ")):
|
238
306
|
function_tracker["in_function"] = True
|
239
307
|
function_tracker["function_indent"] = len(line) - len(stripped_line)
|
@@ -244,7 +312,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
244
312
|
def _is_function_end(
|
245
313
|
self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
|
246
314
|
) -> bool:
|
247
|
-
"""Check if current line marks the end of a function."""
|
248
315
|
return (
|
249
316
|
function_tracker["in_function"]
|
250
317
|
and bool(line)
|
@@ -259,13 +326,10 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
259
326
|
cleaned_lines: list[str],
|
260
327
|
function_tracker: dict[str, t.Any],
|
261
328
|
) -> bool:
|
262
|
-
"""Determine if an empty line should be skipped."""
|
263
329
|
if line_idx > 0 and cleaned_lines and (not cleaned_lines[-1]):
|
264
330
|
return True
|
265
|
-
|
266
331
|
if function_tracker["in_function"]:
|
267
332
|
return self._should_skip_function_empty_line(line_idx, lines)
|
268
|
-
|
269
333
|
return False
|
270
334
|
|
271
335
|
def _should_skip_function_empty_line(self, line_idx: int, lines: list[str]) -> bool:
|
@@ -280,7 +344,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
280
344
|
return True
|
281
345
|
if next_line in ("pass", "break", "continue", "raise"):
|
282
346
|
return True
|
283
|
-
|
284
347
|
return self._is_special_comment(next_line)
|
285
348
|
|
286
349
|
def _is_special_comment(self, line: str) -> bool:
|
@@ -420,15 +483,12 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
420
483
|
for tool, settings in our_toml_config.get("tool", {}).items():
|
421
484
|
if tool not in pkg_toml_config["tool"]:
|
422
485
|
pkg_toml_config["tool"][tool] = {}
|
423
|
-
|
424
486
|
pkg_tool_config = pkg_toml_config["tool"][tool]
|
425
|
-
|
426
487
|
self._merge_tool_config(settings, pkg_tool_config, tool)
|
427
488
|
|
428
489
|
def _merge_tool_config(
|
429
490
|
self, our_config: dict[str, t.Any], pkg_config: dict[str, t.Any], tool: str
|
430
491
|
) -> None:
|
431
|
-
"""Recursively merge tool configuration, preserving existing project settings."""
|
432
492
|
for setting, value in our_config.items():
|
433
493
|
if isinstance(value, dict):
|
434
494
|
self._merge_nested_config(setting, value, pkg_config)
|
@@ -438,21 +498,17 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
438
498
|
def _merge_nested_config(
|
439
499
|
self, setting: str, value: dict[str, t.Any], pkg_config: dict[str, t.Any]
|
440
500
|
) -> None:
|
441
|
-
"""Handle nested configuration merging."""
|
442
501
|
if setting not in pkg_config:
|
443
502
|
pkg_config[setting] = {}
|
444
503
|
elif not isinstance(pkg_config[setting], dict):
|
445
504
|
pkg_config[setting] = {}
|
446
|
-
|
447
505
|
self._merge_tool_config(value, pkg_config[setting], "")
|
448
|
-
|
449
506
|
for k, v in value.items():
|
450
507
|
self._merge_nested_value(k, v, pkg_config[setting])
|
451
508
|
|
452
509
|
def _merge_nested_value(
|
453
510
|
self, key: str, value: t.Any, nested_config: dict[str, t.Any]
|
454
511
|
) -> None:
|
455
|
-
"""Merge individual nested values."""
|
456
512
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
457
513
|
nested_config[key] = self.swap_package_name(value)
|
458
514
|
elif self._is_mergeable_list(key, value):
|
@@ -467,7 +523,6 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
467
523
|
def _merge_direct_config(
|
468
524
|
self, setting: str, value: t.Any, pkg_config: dict[str, t.Any]
|
469
525
|
) -> None:
|
470
|
-
"""Handle direct configuration merging."""
|
471
526
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
472
527
|
pkg_config[setting] = self.swap_package_name(value)
|
473
528
|
elif self._is_mergeable_list(setting, value):
|
@@ -633,7 +688,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
633
688
|
)
|
634
689
|
if result.returncode == 0:
|
635
690
|
self.console.print("PDM installed: ✅\n")
|
636
|
-
self.execute_command(["pdm", "
|
691
|
+
self.execute_command(["pdm", "lock"])
|
637
692
|
self.console.print("Lock file updated: ✅\n")
|
638
693
|
else:
|
639
694
|
self.console.print(
|
@@ -730,7 +785,6 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
730
785
|
self._add_benchmark_flags(test, options)
|
731
786
|
else:
|
732
787
|
self._add_worker_flags(test, options, project_size)
|
733
|
-
|
734
788
|
return test
|
735
789
|
|
736
790
|
def _detect_project_size(self) -> str:
|
crackerjack/errors.py
CHANGED
crackerjack/interactive.py
CHANGED
@@ -2,7 +2,6 @@ import time
|
|
2
2
|
import typing as t
|
3
3
|
from enum import Enum, auto
|
4
4
|
from pathlib import Path
|
5
|
-
|
6
5
|
from rich.box import ROUNDED
|
7
6
|
from rich.console import Console
|
8
7
|
from rich.layout import Layout
|
@@ -19,7 +18,6 @@ from rich.prompt import Confirm, Prompt
|
|
19
18
|
from rich.table import Table
|
20
19
|
from rich.text import Text
|
21
20
|
from rich.tree import Tree
|
22
|
-
|
23
21
|
from .errors import CrackerjackError, ErrorCode, handle_error
|
24
22
|
|
25
23
|
|
@@ -289,7 +287,6 @@ class InteractiveCLI:
|
|
289
287
|
)
|
290
288
|
total_tasks = len(self.workflow.tasks)
|
291
289
|
progress_task = progress.add_task("Running workflow", total=total_tasks)
|
292
|
-
|
293
290
|
return {
|
294
291
|
"progress": progress,
|
295
292
|
"progress_task": progress_task,
|
@@ -299,14 +296,11 @@ class InteractiveCLI:
|
|
299
296
|
def _execute_workflow_loop(
|
300
297
|
self, layout: Layout, progress_tracker: dict[str, t.Any], live: Live
|
301
298
|
) -> None:
|
302
|
-
"""Execute the main workflow loop."""
|
303
299
|
while not self.workflow.all_tasks_completed():
|
304
300
|
layout["tasks"].update(self.show_task_table())
|
305
301
|
next_task = self.workflow.get_next_task()
|
306
|
-
|
307
302
|
if not next_task:
|
308
303
|
break
|
309
|
-
|
310
304
|
if self._should_execute_task(layout, next_task, live):
|
311
305
|
self._execute_task(layout, next_task, progress_tracker)
|
312
306
|
else:
|
@@ -322,20 +316,16 @@ class InteractiveCLI:
|
|
322
316
|
def _execute_task(
|
323
317
|
self, layout: Layout, task: Task, progress_tracker: dict[str, t.Any]
|
324
318
|
) -> None:
|
325
|
-
"""Execute a single task and update progress."""
|
326
319
|
task.start()
|
327
320
|
layout["details"].update(self.show_task_status(task))
|
328
321
|
time.sleep(1)
|
329
|
-
|
330
322
|
success = self._simulate_task_execution()
|
331
|
-
|
332
323
|
if success:
|
333
324
|
task.complete()
|
334
325
|
progress_tracker["completed_tasks"] += 1
|
335
326
|
else:
|
336
327
|
error = self._create_task_error(task.name)
|
337
328
|
task.fail(error)
|
338
|
-
|
339
329
|
progress_tracker["progress"].update(
|
340
330
|
progress_tracker["progress_task"],
|
341
331
|
completed=progress_tracker["completed_tasks"],
|
crackerjack/pyproject.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crackerjack
|
3
|
-
Version: 0.21.
|
3
|
+
Version: 0.21.7
|
4
4
|
Summary: Crackerjack: code quality toolkit
|
5
5
|
Keywords: bandit,black,creosote,mypy,pyright,pytest,refurb,ruff
|
6
6
|
Author-Email: lesleslie <les@wedgwoodwebworks.com>
|
@@ -102,7 +102,7 @@ If you're new to Crackerjack, follow these steps:
|
|
102
102
|
|
103
103
|
Or use the interactive Rich UI:
|
104
104
|
```
|
105
|
-
python -m crackerjack --
|
105
|
+
python -m crackerjack --interactive
|
106
106
|
```
|
107
107
|
|
108
108
|
---
|
@@ -269,7 +269,7 @@ python -m crackerjack -t --benchmark-regression --benchmark-regression-threshold
|
|
269
269
|
|
270
270
|
Or with the interactive Rich UI:
|
271
271
|
```
|
272
|
-
python -m crackerjack --
|
272
|
+
python -m crackerjack --interactive
|
273
273
|
```
|
274
274
|
|
275
275
|
## Usage
|
@@ -361,7 +361,7 @@ runner.process(MyOptions())
|
|
361
361
|
- `--benchmark-regression`: Fail tests if benchmarks regress beyond threshold.
|
362
362
|
- `--benchmark-regression-threshold`: Set threshold percentage for benchmark regression (default 5.0%).
|
363
363
|
- `-a`, `--all`: Run with `-x -t -p <micro|minor|major> -c` development options.
|
364
|
-
- `--
|
364
|
+
- `--interactive`: Enable the interactive Rich UI for a more user-friendly experience with visual progress tracking and interactive prompts.
|
365
365
|
- `--ai-agent`: Enable AI agent mode with structured output (see [AI Agent Integration](#ai-agent-integration)).
|
366
366
|
- `--help`: Display help.
|
367
367
|
|
@@ -461,7 +461,7 @@ runner.process(MyOptions())
|
|
461
461
|
|
462
462
|
- **Rich Interactive Mode** - Run with the interactive Rich UI:
|
463
463
|
```bash
|
464
|
-
python -m crackerjack --
|
464
|
+
python -m crackerjack --interactive
|
465
465
|
```
|
466
466
|
|
467
467
|
- **AI Integration** - Run with structured output for AI tools:
|
@@ -500,10 +500,10 @@ Crackerjack now offers an enhanced interactive experience through its Rich UI:
|
|
500
500
|
- **Error Visualization:** Errors are presented in a structured, easy-to-understand format with recovery suggestions
|
501
501
|
- **File Selection:** Interactive file browser for operations that require selecting files
|
502
502
|
|
503
|
-
To use the Rich UI, run Crackerjack with the `--
|
503
|
+
To use the Rich UI, run Crackerjack with the `--interactive` flag:
|
504
504
|
|
505
505
|
```bash
|
506
|
-
python -m crackerjack --
|
506
|
+
python -m crackerjack --interactive
|
507
507
|
```
|
508
508
|
|
509
509
|
This launches an interactive terminal interface where you can:
|
@@ -542,7 +542,7 @@ python -m crackerjack -v
|
|
542
542
|
For the most comprehensive error details with visual formatting, combine verbose mode with the Rich UI:
|
543
543
|
|
544
544
|
```bash
|
545
|
-
python -m crackerjack --
|
545
|
+
python -m crackerjack --interactive -v
|
546
546
|
```
|
547
547
|
|
548
548
|
## Python 3.13+ Features
|
@@ -1,8 +1,8 @@
|
|
1
|
-
crackerjack-0.21.
|
2
|
-
crackerjack-0.21.
|
3
|
-
crackerjack-0.21.
|
4
|
-
crackerjack-0.21.
|
5
|
-
crackerjack/.gitignore,sha256=
|
1
|
+
crackerjack-0.21.7.dist-info/METADATA,sha256=suf-qK6MQQTYL6v8ZXcTUT70x6ADX6u1Dd8YvhQSV60,26442
|
2
|
+
crackerjack-0.21.7.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
|
3
|
+
crackerjack-0.21.7.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
4
|
+
crackerjack-0.21.7.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
|
5
|
+
crackerjack/.gitignore,sha256=n8cD6U16L3XZn__PvhYm_F7-YeFHFucHCyxWj2NZCGs,259
|
6
6
|
crackerjack/.libcst.codemod.yaml,sha256=a8DlErRAIPV1nE6QlyXPAzTOgkB24_spl2E9hphuf5s,772
|
7
7
|
crackerjack/.pdm.toml,sha256=dZe44HRcuxxCFESGG8SZIjmc-cGzSoyK3Hs6t4NYA8w,23
|
8
8
|
crackerjack/.pre-commit-config-ai.yaml,sha256=K8xXKMJcdhfXOk24L4XpK7H8YlvnZfOh4NVA6qvOz8I,3319
|
@@ -34,7 +34,7 @@ crackerjack/.ruff_cache/0.11.7/10386934055395314831,sha256=lBNwN5zAgM4OzbkXIOzCc
|
|
34
34
|
crackerjack/.ruff_cache/0.11.7/3557596832929915217,sha256=fKlwUbsvT3YIKV6UR-aA_i64lLignWeVfVu-MMmVbU0,207
|
35
35
|
crackerjack/.ruff_cache/0.11.8/530407680854991027,sha256=xAMAL3Vu_HR6M-h5ojCTaak0By5ii8u-14pXULLgLqw,224
|
36
36
|
crackerjack/.ruff_cache/0.12.0/5056746222905752453,sha256=MqrIT5qymJcgAOBZyn-TvYoGCFfDFCgN9IwSULq8n14,256
|
37
|
-
crackerjack/.ruff_cache/0.12.1/5056746222905752453,sha256=
|
37
|
+
crackerjack/.ruff_cache/0.12.1/5056746222905752453,sha256=CHy2IV23GK0EauutmCmddO7Ck-fHMzbvpvZ1ZO9Cp8Y,256
|
38
38
|
crackerjack/.ruff_cache/0.2.0/10047773857155985907,sha256=j9LNa_RQ4Plor7go1uTYgz17cEENKvZQ-dP6b9MX0ik,248
|
39
39
|
crackerjack/.ruff_cache/0.2.1/8522267973936635051,sha256=u_aPBMibtAp_iYvLwR88GMAECMcIgHezxMyuapmU2P4,248
|
40
40
|
crackerjack/.ruff_cache/0.2.2/18053836298936336950,sha256=Xb_ebP0pVuUfSqPEZKlhQ70so_vqkEfMYpuHQ06iR5U,248
|
@@ -62,11 +62,11 @@ crackerjack/.ruff_cache/0.9.3/13948373885254993391,sha256=kGhtIkzPUtKAgvlKs3D8j4
|
|
62
62
|
crackerjack/.ruff_cache/0.9.9/12813592349865671909,sha256=tmr8_vhRD2OxsVuMfbJPdT9fDFX-d5tfC5U9jgziyho,224
|
63
63
|
crackerjack/.ruff_cache/0.9.9/8843823720003377982,sha256=e4ymkXfQsUg5e_mtO34xTsaTvs1uA3_fI216Qq9qCAM,136
|
64
64
|
crackerjack/.ruff_cache/CACHEDIR.TAG,sha256=WVMVbX4MVkpCclExbq8m-IcOZIOuIZf5FrYw5Pk-Ma4,43
|
65
|
-
crackerjack/__init__.py,sha256=
|
66
|
-
crackerjack/__main__.py,sha256=
|
67
|
-
crackerjack/crackerjack.py,sha256=
|
68
|
-
crackerjack/errors.py,sha256=
|
69
|
-
crackerjack/interactive.py,sha256=
|
65
|
+
crackerjack/__init__.py,sha256=LyIPEfjBcqWp7UVuJ-b7cc8oiFxrQqyL8RJ7g6c17Qs,838
|
66
|
+
crackerjack/__main__.py,sha256=GP5GBbWK5lDTQanCHKVEyS3hDWvshwlrhWagzQlRuD4,6560
|
67
|
+
crackerjack/crackerjack.py,sha256=jlepiHgMkvTyl83O8HUqC4mCsQbZIejerOHNQD15JcU,35854
|
68
|
+
crackerjack/errors.py,sha256=xvXO3bk0VrxQz0lysIuVOju6SxxDgf04Wne1BedLFB8,4061
|
69
|
+
crackerjack/interactive.py,sha256=ierA2jeUsigTJhKOcJJsjhBZm2WwsQpvow3Y5ppF7IE,16151
|
70
70
|
crackerjack/py313.py,sha256=buYE7LO11Q64ffowEhTZRFQoAGj_8sg3DTlZuv8M9eo,5890
|
71
|
-
crackerjack/pyproject.toml,sha256=
|
72
|
-
crackerjack-0.21.
|
71
|
+
crackerjack/pyproject.toml,sha256=OIoNmIktC1abFPgePb95Zg9BDTGfRxXftK-KccWgalc,4988
|
72
|
+
crackerjack-0.21.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|