crackerjack 0.21.6__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/.ruff_cache/0.12.1/5056746222905752453 +0 -0
- crackerjack/__init__.py +0 -1
- crackerjack/__main__.py +0 -1
- crackerjack/crackerjack.py +81 -70
- crackerjack/errors.py +0 -1
- crackerjack/interactive.py +0 -10
- crackerjack/pyproject.toml +1 -1
- {crackerjack-0.21.6.dist-info → crackerjack-0.21.7.dist-info}/METADATA +8 -8
- {crackerjack-0.21.6.dist-info → crackerjack-0.21.7.dist-info}/RECORD +12 -12
- {crackerjack-0.21.6.dist-info → crackerjack-0.21.7.dist-info}/WHEEL +0 -0
- {crackerjack-0.21.6.dist-info → crackerjack-0.21.7.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.21.6.dist-info → crackerjack-0.21.7.dist-info}/licenses/LICENSE +0 -0
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,55 +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
|
|
89
|
-
def
|
90
|
-
|
91
|
-
cleaned_lines = []
|
92
|
-
docstring_state = {
|
88
|
+
def _initialize_docstring_state(self) -> dict[str, t.Any]:
|
89
|
+
return {
|
93
90
|
"in_docstring": False,
|
94
91
|
"delimiter": None,
|
95
92
|
"waiting": False,
|
96
93
|
"function_indent": 0,
|
97
94
|
"removed_docstring": False,
|
95
|
+
"in_multiline_def": False,
|
98
96
|
}
|
99
|
-
for i, line in enumerate(lines):
|
100
|
-
stripped = line.strip()
|
101
|
-
if self._is_function_or_class_definition(stripped):
|
102
|
-
docstring_state["waiting"] = True
|
103
|
-
docstring_state["function_indent"] = len(line) - len(line.lstrip())
|
104
|
-
docstring_state["removed_docstring"] = False
|
105
|
-
cleaned_lines.append(line)
|
106
|
-
continue
|
107
|
-
if docstring_state["waiting"] and stripped:
|
108
|
-
if self._handle_docstring_start(stripped, docstring_state):
|
109
|
-
if not docstring_state["in_docstring"]:
|
110
|
-
if self._needs_pass_statement(
|
111
|
-
lines, i + 1, docstring_state["function_indent"]
|
112
|
-
):
|
113
|
-
pass_line = (
|
114
|
-
" " * (docstring_state["function_indent"] + 4) + "pass"
|
115
|
-
)
|
116
|
-
cleaned_lines.append(pass_line)
|
117
|
-
docstring_state["removed_docstring"] = True
|
118
|
-
continue
|
119
|
-
else:
|
120
|
-
docstring_state["waiting"] = False
|
121
|
-
if docstring_state["in_docstring"]:
|
122
|
-
if self._handle_docstring_end(stripped, docstring_state):
|
123
|
-
if self._needs_pass_statement(
|
124
|
-
lines, i + 1, docstring_state["function_indent"]
|
125
|
-
):
|
126
|
-
pass_line = (
|
127
|
-
" " * (docstring_state["function_indent"] + 4) + "pass"
|
128
|
-
)
|
129
|
-
cleaned_lines.append(pass_line)
|
130
|
-
docstring_state["removed_docstring"] = False
|
131
|
-
continue
|
132
|
-
else:
|
133
|
-
continue
|
134
|
-
if docstring_state["removed_docstring"] and stripped:
|
135
|
-
docstring_state["removed_docstring"] = False
|
136
|
-
cleaned_lines.append(line)
|
137
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
|
+
|
167
|
+
def remove_docstrings(self, code: str) -> str:
|
168
|
+
lines = code.split("\n")
|
169
|
+
cleaned_lines = []
|
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)
|
138
175
|
return "\n".join(cleaned_lines)
|
139
176
|
|
140
177
|
def _is_function_or_class_definition(self, stripped_line: str) -> bool:
|
@@ -177,9 +214,8 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
177
214
|
line_indent = len(line) - len(line.lstrip())
|
178
215
|
if line_indent <= function_indent:
|
179
216
|
return True
|
180
|
-
if line_indent
|
217
|
+
if line_indent > function_indent:
|
181
218
|
return False
|
182
|
-
|
183
219
|
return True
|
184
220
|
|
185
221
|
def remove_line_comments(self, code: str) -> str:
|
@@ -192,7 +228,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
192
228
|
cleaned_line = self._process_line_for_comments(line)
|
193
229
|
if cleaned_line or not line.strip():
|
194
230
|
cleaned_lines.append(cleaned_line or line)
|
195
|
-
|
196
231
|
return "\n".join(cleaned_lines)
|
197
232
|
|
198
233
|
def _process_line_for_comments(self, line: str) -> str:
|
@@ -205,7 +240,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
205
240
|
break
|
206
241
|
else:
|
207
242
|
result.append(char)
|
208
|
-
|
209
243
|
return "".join(result).rstrip()
|
210
244
|
|
211
245
|
def _handle_string_character(
|
@@ -216,18 +250,14 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
216
250
|
string_state: dict[str, t.Any],
|
217
251
|
result: list[str],
|
218
252
|
) -> bool:
|
219
|
-
"""Handle string quote characters. Returns True if character was handled."""
|
220
253
|
if char not in ("'", '"'):
|
221
254
|
return False
|
222
|
-
|
223
255
|
if index > 0 and line[index - 1] == "\\":
|
224
256
|
return False
|
225
|
-
|
226
257
|
if string_state["in_string"] is None:
|
227
258
|
string_state["in_string"] = char
|
228
259
|
elif string_state["in_string"] == char:
|
229
260
|
string_state["in_string"] = None
|
230
|
-
|
231
261
|
result.append(char)
|
232
262
|
return True
|
233
263
|
|
@@ -239,14 +269,11 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
239
269
|
string_state: dict[str, t.Any],
|
240
270
|
result: list[str],
|
241
271
|
) -> bool:
|
242
|
-
"""Handle comment character. Returns True if comment was found."""
|
243
272
|
if char != "#" or string_state["in_string"] is not None:
|
244
273
|
return False
|
245
|
-
|
246
274
|
comment = line[index:].strip()
|
247
275
|
if self._is_special_comment_line(comment):
|
248
276
|
result.append(line[index:])
|
249
|
-
|
250
277
|
return True
|
251
278
|
|
252
279
|
def _is_special_comment_line(self, comment: str) -> bool:
|
@@ -270,13 +297,11 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
270
297
|
):
|
271
298
|
continue
|
272
299
|
cleaned_lines.append(line)
|
273
|
-
|
274
300
|
return "\n".join(self._remove_trailing_empty_lines(cleaned_lines))
|
275
301
|
|
276
302
|
def _update_function_state(
|
277
303
|
self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
|
278
304
|
) -> None:
|
279
|
-
"""Update function tracking state based on current line."""
|
280
305
|
if stripped_line.startswith(("def ", "async def ")):
|
281
306
|
function_tracker["in_function"] = True
|
282
307
|
function_tracker["function_indent"] = len(line) - len(stripped_line)
|
@@ -287,7 +312,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
287
312
|
def _is_function_end(
|
288
313
|
self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
|
289
314
|
) -> bool:
|
290
|
-
"""Check if current line marks the end of a function."""
|
291
315
|
return (
|
292
316
|
function_tracker["in_function"]
|
293
317
|
and bool(line)
|
@@ -302,13 +326,10 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
302
326
|
cleaned_lines: list[str],
|
303
327
|
function_tracker: dict[str, t.Any],
|
304
328
|
) -> bool:
|
305
|
-
"""Determine if an empty line should be skipped."""
|
306
329
|
if line_idx > 0 and cleaned_lines and (not cleaned_lines[-1]):
|
307
330
|
return True
|
308
|
-
|
309
331
|
if function_tracker["in_function"]:
|
310
332
|
return self._should_skip_function_empty_line(line_idx, lines)
|
311
|
-
|
312
333
|
return False
|
313
334
|
|
314
335
|
def _should_skip_function_empty_line(self, line_idx: int, lines: list[str]) -> bool:
|
@@ -323,7 +344,6 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
323
344
|
return True
|
324
345
|
if next_line in ("pass", "break", "continue", "raise"):
|
325
346
|
return True
|
326
|
-
|
327
347
|
return self._is_special_comment(next_line)
|
328
348
|
|
329
349
|
def _is_special_comment(self, line: str) -> bool:
|
@@ -463,15 +483,12 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
463
483
|
for tool, settings in our_toml_config.get("tool", {}).items():
|
464
484
|
if tool not in pkg_toml_config["tool"]:
|
465
485
|
pkg_toml_config["tool"][tool] = {}
|
466
|
-
|
467
486
|
pkg_tool_config = pkg_toml_config["tool"][tool]
|
468
|
-
|
469
487
|
self._merge_tool_config(settings, pkg_tool_config, tool)
|
470
488
|
|
471
489
|
def _merge_tool_config(
|
472
490
|
self, our_config: dict[str, t.Any], pkg_config: dict[str, t.Any], tool: str
|
473
491
|
) -> None:
|
474
|
-
"""Recursively merge tool configuration, preserving existing project settings."""
|
475
492
|
for setting, value in our_config.items():
|
476
493
|
if isinstance(value, dict):
|
477
494
|
self._merge_nested_config(setting, value, pkg_config)
|
@@ -481,21 +498,17 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
481
498
|
def _merge_nested_config(
|
482
499
|
self, setting: str, value: dict[str, t.Any], pkg_config: dict[str, t.Any]
|
483
500
|
) -> None:
|
484
|
-
"""Handle nested configuration merging."""
|
485
501
|
if setting not in pkg_config:
|
486
502
|
pkg_config[setting] = {}
|
487
503
|
elif not isinstance(pkg_config[setting], dict):
|
488
504
|
pkg_config[setting] = {}
|
489
|
-
|
490
505
|
self._merge_tool_config(value, pkg_config[setting], "")
|
491
|
-
|
492
506
|
for k, v in value.items():
|
493
507
|
self._merge_nested_value(k, v, pkg_config[setting])
|
494
508
|
|
495
509
|
def _merge_nested_value(
|
496
510
|
self, key: str, value: t.Any, nested_config: dict[str, t.Any]
|
497
511
|
) -> None:
|
498
|
-
"""Merge individual nested values."""
|
499
512
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
500
513
|
nested_config[key] = self.swap_package_name(value)
|
501
514
|
elif self._is_mergeable_list(key, value):
|
@@ -510,7 +523,6 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
510
523
|
def _merge_direct_config(
|
511
524
|
self, setting: str, value: t.Any, pkg_config: dict[str, t.Any]
|
512
525
|
) -> None:
|
513
|
-
"""Handle direct configuration merging."""
|
514
526
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
515
527
|
pkg_config[setting] = self.swap_package_name(value)
|
516
528
|
elif self._is_mergeable_list(setting, value):
|
@@ -773,7 +785,6 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
773
785
|
self._add_benchmark_flags(test, options)
|
774
786
|
else:
|
775
787
|
self._add_worker_flags(test, options, project_size)
|
776
|
-
|
777
788
|
return test
|
778
789
|
|
779
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,7 +1,7 @@
|
|
1
|
-
crackerjack-0.21.
|
2
|
-
crackerjack-0.21.
|
3
|
-
crackerjack-0.21.
|
4
|
-
crackerjack-0.21.
|
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
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
|
@@ -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
|