crackerjack 0.21.7__tar.gz → 0.22.0__tar.gz
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-0.21.7 → crackerjack-0.22.0}/PKG-INFO +10 -12
- {crackerjack-0.21.7 → crackerjack-0.22.0}/README.md +9 -11
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pre-commit-config.yaml +1 -17
- crackerjack-0.22.0/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/__init__.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/__main__.py +1 -4
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/crackerjack.py +148 -5
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/errors.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/interactive.py +2 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/pyproject.toml +1 -1
- {crackerjack-0.21.7 → crackerjack-0.22.0}/pyproject.toml +1 -1
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/conftest.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_crackerjack.py +4 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_crackerjack_runner.py +1 -1
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_errors.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_interactive.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_interactive_run.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_main.py +3 -19
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_multiline_functions.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_py313_advanced.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_py313_features.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_pytest_features.py +1 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/test_structured_errors.py +1 -0
- crackerjack-0.21.7/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/LICENSE +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.gitignore +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.libcst.codemod.yaml +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pdm.toml +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pre-commit-config-ai.yaml +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pytest_cache/.gitignore +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pytest_cache/CACHEDIR.TAG +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pytest_cache/README.md +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pytest_cache/v/cache/nodeids +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.pytest_cache/v/cache/stepwise +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/.gitignore +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.11/18187162184424859798 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/16869036553936192448 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/1867267426380906393 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/4240757255861806333 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/4441409093023629623 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.13/1867267426380906393 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.13/4240757255861806333 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.12.0/5056746222905752453 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/CACHEDIR.TAG +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/py313.py +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/TESTING.md +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/__init__.py +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/data/comments_sample.txt +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/data/docstrings_sample.txt +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/data/expected_comments_sample.txt +0 -0
- {crackerjack-0.21.7 → crackerjack-0.22.0}/tests/data/init.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crackerjack
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.22.0
|
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 -i
|
106
106
|
```
|
107
107
|
|
108
108
|
---
|
@@ -160,7 +160,7 @@ Crackerjack automatically installs and manages these pre-commit hooks:
|
|
160
160
|
3. **Ruff:** [Ruff](https://github.com/astral-sh/ruff) for linting, code formatting, and general code style enforcement.
|
161
161
|
4. **Vulture:** [Vulture](https://github.com/jendrikseipp/vulture) to identify dead code.
|
162
162
|
5. **Creosote:** [Creosote](https://github.com/fredrikaverpil/creosote) to detect unused dependencies.
|
163
|
-
6. **
|
163
|
+
6. **Complexipy:** [Complexipy](https://github.com/rohaquinlop/complexipy-pre-commit) for analyzing code complexity.
|
164
164
|
7. **Codespell:** [Codespell](https://github.com/codespell-project/codespell) for correcting typos in the code.
|
165
165
|
8. **Autotyping:** [Autotyping](https://github.com/JelleZijlstra/autotyping) for adding type hints.
|
166
166
|
9. **Refurb:** [Refurb](https://github.com/dosisod/refurb) to suggest code improvements.
|
@@ -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 -i
|
273
273
|
```
|
274
274
|
|
275
275
|
## Usage
|
@@ -301,7 +301,6 @@ class MyOptions:
|
|
301
301
|
# Configuration options
|
302
302
|
self.no_config_updates = False # Skip updating config files
|
303
303
|
self.update_precommit = False # Update pre-commit hooks
|
304
|
-
self.doc = False # Generate documentation (not implemented yet)
|
305
304
|
|
306
305
|
# Process options
|
307
306
|
self.clean = True # Clean code (remove docstrings, comments, etc.)
|
@@ -347,7 +346,6 @@ runner.process(MyOptions())
|
|
347
346
|
- `-i`, `--interactive`: Run pre-commit hooks interactively when possible.
|
348
347
|
- `-n`, `--no-config-updates`: Skip updating configuration files (e.g., `pyproject.toml`).
|
349
348
|
- `-u`, `--update-precommit`: Update pre-commit hooks to the latest versions.
|
350
|
-
- `-d`, `--doc`: Generate documentation. (not yet implemented)
|
351
349
|
- `-v`, `--verbose`: Enable verbose output.
|
352
350
|
- `-p`, `--publish <micro|minor|major>`: Bump the project version and publish to PyPI using PDM.
|
353
351
|
- `-b`, `--bump <micro|minor|major>`: Bump the project version without publishing.
|
@@ -361,7 +359,7 @@ runner.process(MyOptions())
|
|
361
359
|
- `--benchmark-regression`: Fail tests if benchmarks regress beyond threshold.
|
362
360
|
- `--benchmark-regression-threshold`: Set threshold percentage for benchmark regression (default 5.0%).
|
363
361
|
- `-a`, `--all`: Run with `-x -t -p <micro|minor|major> -c` development options.
|
364
|
-
- `--interactive`: Enable the interactive Rich UI for a more user-friendly experience with visual progress tracking and interactive prompts.
|
362
|
+
- `-i`, `--interactive`: Enable the interactive Rich UI for a more user-friendly experience with visual progress tracking and interactive prompts.
|
365
363
|
- `--ai-agent`: Enable AI agent mode with structured output (see [AI Agent Integration](#ai-agent-integration)).
|
366
364
|
- `--help`: Display help.
|
367
365
|
|
@@ -461,7 +459,7 @@ runner.process(MyOptions())
|
|
461
459
|
|
462
460
|
- **Rich Interactive Mode** - Run with the interactive Rich UI:
|
463
461
|
```bash
|
464
|
-
python -m crackerjack
|
462
|
+
python -m crackerjack -i
|
465
463
|
```
|
466
464
|
|
467
465
|
- **AI Integration** - Run with structured output for AI tools:
|
@@ -500,10 +498,10 @@ Crackerjack now offers an enhanced interactive experience through its Rich UI:
|
|
500
498
|
- **Error Visualization:** Errors are presented in a structured, easy-to-understand format with recovery suggestions
|
501
499
|
- **File Selection:** Interactive file browser for operations that require selecting files
|
502
500
|
|
503
|
-
To use the Rich UI, run Crackerjack with the
|
501
|
+
To use the Rich UI, run Crackerjack with the `-i` flag:
|
504
502
|
|
505
503
|
```bash
|
506
|
-
python -m crackerjack
|
504
|
+
python -m crackerjack -i
|
507
505
|
```
|
508
506
|
|
509
507
|
This launches an interactive terminal interface where you can:
|
@@ -542,7 +540,7 @@ python -m crackerjack -v
|
|
542
540
|
For the most comprehensive error details with visual formatting, combine verbose mode with the Rich UI:
|
543
541
|
|
544
542
|
```bash
|
545
|
-
python -m crackerjack
|
543
|
+
python -m crackerjack -i -v
|
546
544
|
```
|
547
545
|
|
548
546
|
## Python 3.13+ Features
|
@@ -606,7 +604,7 @@ Crackerjack is designed with modern Python principles in mind:
|
|
606
604
|
- **bandit:** For finding security vulnerabilities.
|
607
605
|
- **vulture:** For dead code detection.
|
608
606
|
- **creosote:** For unused dependency detection.
|
609
|
-
- **
|
607
|
+
- **complexipy:** For code complexity analysis.
|
610
608
|
- **codespell:** For spelling correction.
|
611
609
|
- **autotyping:** For automatically adding type hints.
|
612
610
|
- **refurb:** For code improvement suggestions.
|
@@ -58,7 +58,7 @@ If you're new to Crackerjack, follow these steps:
|
|
58
58
|
|
59
59
|
Or use the interactive Rich UI:
|
60
60
|
```
|
61
|
-
python -m crackerjack
|
61
|
+
python -m crackerjack -i
|
62
62
|
```
|
63
63
|
|
64
64
|
---
|
@@ -116,7 +116,7 @@ Crackerjack automatically installs and manages these pre-commit hooks:
|
|
116
116
|
3. **Ruff:** [Ruff](https://github.com/astral-sh/ruff) for linting, code formatting, and general code style enforcement.
|
117
117
|
4. **Vulture:** [Vulture](https://github.com/jendrikseipp/vulture) to identify dead code.
|
118
118
|
5. **Creosote:** [Creosote](https://github.com/fredrikaverpil/creosote) to detect unused dependencies.
|
119
|
-
6. **
|
119
|
+
6. **Complexipy:** [Complexipy](https://github.com/rohaquinlop/complexipy-pre-commit) for analyzing code complexity.
|
120
120
|
7. **Codespell:** [Codespell](https://github.com/codespell-project/codespell) for correcting typos in the code.
|
121
121
|
8. **Autotyping:** [Autotyping](https://github.com/JelleZijlstra/autotyping) for adding type hints.
|
122
122
|
9. **Refurb:** [Refurb](https://github.com/dosisod/refurb) to suggest code improvements.
|
@@ -225,7 +225,7 @@ python -m crackerjack -t --benchmark-regression --benchmark-regression-threshold
|
|
225
225
|
|
226
226
|
Or with the interactive Rich UI:
|
227
227
|
```
|
228
|
-
python -m crackerjack
|
228
|
+
python -m crackerjack -i
|
229
229
|
```
|
230
230
|
|
231
231
|
## Usage
|
@@ -257,7 +257,6 @@ class MyOptions:
|
|
257
257
|
# Configuration options
|
258
258
|
self.no_config_updates = False # Skip updating config files
|
259
259
|
self.update_precommit = False # Update pre-commit hooks
|
260
|
-
self.doc = False # Generate documentation (not implemented yet)
|
261
260
|
|
262
261
|
# Process options
|
263
262
|
self.clean = True # Clean code (remove docstrings, comments, etc.)
|
@@ -303,7 +302,6 @@ runner.process(MyOptions())
|
|
303
302
|
- `-i`, `--interactive`: Run pre-commit hooks interactively when possible.
|
304
303
|
- `-n`, `--no-config-updates`: Skip updating configuration files (e.g., `pyproject.toml`).
|
305
304
|
- `-u`, `--update-precommit`: Update pre-commit hooks to the latest versions.
|
306
|
-
- `-d`, `--doc`: Generate documentation. (not yet implemented)
|
307
305
|
- `-v`, `--verbose`: Enable verbose output.
|
308
306
|
- `-p`, `--publish <micro|minor|major>`: Bump the project version and publish to PyPI using PDM.
|
309
307
|
- `-b`, `--bump <micro|minor|major>`: Bump the project version without publishing.
|
@@ -317,7 +315,7 @@ runner.process(MyOptions())
|
|
317
315
|
- `--benchmark-regression`: Fail tests if benchmarks regress beyond threshold.
|
318
316
|
- `--benchmark-regression-threshold`: Set threshold percentage for benchmark regression (default 5.0%).
|
319
317
|
- `-a`, `--all`: Run with `-x -t -p <micro|minor|major> -c` development options.
|
320
|
-
- `--interactive`: Enable the interactive Rich UI for a more user-friendly experience with visual progress tracking and interactive prompts.
|
318
|
+
- `-i`, `--interactive`: Enable the interactive Rich UI for a more user-friendly experience with visual progress tracking and interactive prompts.
|
321
319
|
- `--ai-agent`: Enable AI agent mode with structured output (see [AI Agent Integration](#ai-agent-integration)).
|
322
320
|
- `--help`: Display help.
|
323
321
|
|
@@ -417,7 +415,7 @@ runner.process(MyOptions())
|
|
417
415
|
|
418
416
|
- **Rich Interactive Mode** - Run with the interactive Rich UI:
|
419
417
|
```bash
|
420
|
-
python -m crackerjack
|
418
|
+
python -m crackerjack -i
|
421
419
|
```
|
422
420
|
|
423
421
|
- **AI Integration** - Run with structured output for AI tools:
|
@@ -456,10 +454,10 @@ Crackerjack now offers an enhanced interactive experience through its Rich UI:
|
|
456
454
|
- **Error Visualization:** Errors are presented in a structured, easy-to-understand format with recovery suggestions
|
457
455
|
- **File Selection:** Interactive file browser for operations that require selecting files
|
458
456
|
|
459
|
-
To use the Rich UI, run Crackerjack with the
|
457
|
+
To use the Rich UI, run Crackerjack with the `-i` flag:
|
460
458
|
|
461
459
|
```bash
|
462
|
-
python -m crackerjack
|
460
|
+
python -m crackerjack -i
|
463
461
|
```
|
464
462
|
|
465
463
|
This launches an interactive terminal interface where you can:
|
@@ -498,7 +496,7 @@ python -m crackerjack -v
|
|
498
496
|
For the most comprehensive error details with visual formatting, combine verbose mode with the Rich UI:
|
499
497
|
|
500
498
|
```bash
|
501
|
-
python -m crackerjack
|
499
|
+
python -m crackerjack -i -v
|
502
500
|
```
|
503
501
|
|
504
502
|
## Python 3.13+ Features
|
@@ -562,7 +560,7 @@ Crackerjack is designed with modern Python principles in mind:
|
|
562
560
|
- **bandit:** For finding security vulnerabilities.
|
563
561
|
- **vulture:** For dead code detection.
|
564
562
|
- **creosote:** For unused dependency detection.
|
565
|
-
- **
|
563
|
+
- **complexipy:** For code complexity analysis.
|
566
564
|
- **codespell:** For spelling correction.
|
567
565
|
- **autotyping:** For automatically adding type hints.
|
568
566
|
- **refurb:** For code improvement suggestions.
|
@@ -14,11 +14,6 @@ repos:
|
|
14
14
|
- id: check-added-large-files
|
15
15
|
name: check-added-large-files
|
16
16
|
|
17
|
-
- repo: https://github.com/abravalheri/validate-pyproject
|
18
|
-
rev: v0.24.1
|
19
|
-
hooks:
|
20
|
-
- id: validate-pyproject
|
21
|
-
|
22
17
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
23
18
|
rev: "v2.6.0"
|
24
19
|
hooks:
|
@@ -34,7 +29,7 @@ repos:
|
|
34
29
|
- keyring
|
35
30
|
|
36
31
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
37
|
-
rev: 0.7.
|
32
|
+
rev: 0.7.16
|
38
33
|
hooks:
|
39
34
|
- id: uv-lock
|
40
35
|
files: ^pyproject\.toml$
|
@@ -110,14 +105,3 @@ repos:
|
|
110
105
|
rev: v1.1.402
|
111
106
|
hooks:
|
112
107
|
- id: pyright
|
113
|
-
|
114
|
-
# - repo: https://github.com/pdoc3/pdoc
|
115
|
-
# rev: master
|
116
|
-
# hooks:
|
117
|
-
# - id: pdoc
|
118
|
-
# name: pdoc
|
119
|
-
# entry: pdoc --html -f -o docs module1 module2 module3
|
120
|
-
# language_version: python3.11
|
121
|
-
# require_serial: true
|
122
|
-
# types: [ python ]
|
123
|
-
# always_run: true
|
Binary file
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from enum import Enum
|
2
|
+
|
2
3
|
import typer
|
3
4
|
from pydantic import BaseModel, field_validator
|
4
5
|
from rich.console import Console
|
@@ -22,7 +23,6 @@ class BumpOption(str, Enum):
|
|
22
23
|
class Options(BaseModel):
|
23
24
|
commit: bool = False
|
24
25
|
interactive: bool = False
|
25
|
-
doc: bool = False
|
26
26
|
no_config_updates: bool = False
|
27
27
|
publish: BumpOption | None = None
|
28
28
|
bump: BumpOption | None = None
|
@@ -62,7 +62,6 @@ cli_options = {
|
|
62
62
|
"--interactive",
|
63
63
|
help="Use the interactive Rich UI for a better experience.",
|
64
64
|
),
|
65
|
-
"doc": typer.Option(False, "-d", "--doc", help="Generate documentation."),
|
66
65
|
"no_config_updates": typer.Option(
|
67
66
|
False, "-n", "--no-config-updates", help="Do not update configuration files."
|
68
67
|
),
|
@@ -145,7 +144,6 @@ cli_options = {
|
|
145
144
|
def main(
|
146
145
|
commit: bool = cli_options["commit"],
|
147
146
|
interactive: bool = cli_options["interactive"],
|
148
|
-
doc: bool = cli_options["doc"],
|
149
147
|
no_config_updates: bool = cli_options["no_config_updates"],
|
150
148
|
update_precommit: bool = cli_options["update_precommit"],
|
151
149
|
verbose: bool = cli_options["verbose"],
|
@@ -168,7 +166,6 @@ def main(
|
|
168
166
|
options = Options(
|
169
167
|
commit=commit,
|
170
168
|
interactive=interactive,
|
171
|
-
doc=doc,
|
172
169
|
no_config_updates=no_config_updates,
|
173
170
|
update_precommit=update_precommit,
|
174
171
|
verbose=verbose,
|
@@ -6,6 +6,7 @@ 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
|
+
|
9
10
|
from pydantic import BaseModel
|
10
11
|
from rich.console import Console
|
11
12
|
from tomli_w import dumps
|
@@ -31,7 +32,6 @@ class CommandRunner(t.Protocol):
|
|
31
32
|
class OptionsProtocol(t.Protocol):
|
32
33
|
commit: bool
|
33
34
|
interactive: bool
|
34
|
-
doc: bool
|
35
35
|
no_config_updates: bool
|
36
36
|
verbose: bool
|
37
37
|
update_precommit: bool
|
@@ -169,9 +169,12 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
169
169
|
cleaned_lines = []
|
170
170
|
docstring_state = self._initialize_docstring_state()
|
171
171
|
for i, line in enumerate(lines):
|
172
|
-
|
173
|
-
if
|
174
|
-
|
172
|
+
handled, result_line = self._process_line(lines, i, line, docstring_state)
|
173
|
+
if handled:
|
174
|
+
if result_line is not None:
|
175
|
+
cleaned_lines.append(result_line)
|
176
|
+
else:
|
177
|
+
cleaned_lines.append(line)
|
175
178
|
return "\n".join(cleaned_lines)
|
176
179
|
|
177
180
|
def _is_function_or_class_definition(self, stripped_line: str) -> bool:
|
@@ -287,13 +290,15 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
287
290
|
lines = code.split("\n")
|
288
291
|
cleaned_lines = []
|
289
292
|
function_tracker = {"in_function": False, "function_indent": 0}
|
293
|
+
import_tracker = {"in_imports": False, "last_import_type": None}
|
290
294
|
for i, line in enumerate(lines):
|
291
295
|
line = line.rstrip()
|
292
296
|
stripped_line = line.lstrip()
|
293
297
|
self._update_function_state(line, stripped_line, function_tracker)
|
298
|
+
self._update_import_state(line, stripped_line, import_tracker)
|
294
299
|
if not line:
|
295
300
|
if self._should_skip_empty_line(
|
296
|
-
i, lines, cleaned_lines, function_tracker
|
301
|
+
i, lines, cleaned_lines, function_tracker, import_tracker
|
297
302
|
):
|
298
303
|
continue
|
299
304
|
cleaned_lines.append(line)
|
@@ -309,6 +314,113 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
309
314
|
function_tracker["in_function"] = False
|
310
315
|
function_tracker["function_indent"] = 0
|
311
316
|
|
317
|
+
def _update_import_state(
|
318
|
+
self, line: str, stripped_line: str, import_tracker: dict[str, t.Any]
|
319
|
+
) -> None:
|
320
|
+
if stripped_line.startswith(("import ", "from ")):
|
321
|
+
import_tracker["in_imports"] = True
|
322
|
+
if self._is_stdlib_import(stripped_line):
|
323
|
+
current_type = "stdlib"
|
324
|
+
elif self._is_local_import(stripped_line):
|
325
|
+
current_type = "local"
|
326
|
+
else:
|
327
|
+
current_type = "third_party"
|
328
|
+
import_tracker["last_import_type"] = current_type
|
329
|
+
elif stripped_line and not stripped_line.startswith("#"):
|
330
|
+
import_tracker["in_imports"] = False
|
331
|
+
import_tracker["last_import_type"] = None
|
332
|
+
|
333
|
+
def _is_stdlib_import(self, stripped_line: str) -> bool:
|
334
|
+
try:
|
335
|
+
if stripped_line.startswith("from "):
|
336
|
+
module = stripped_line.split()[1].split(".")[0]
|
337
|
+
else:
|
338
|
+
module = stripped_line.split()[1].split(".")[0]
|
339
|
+
except IndexError:
|
340
|
+
return False
|
341
|
+
stdlib_modules = {
|
342
|
+
"os",
|
343
|
+
"sys",
|
344
|
+
"re",
|
345
|
+
"json",
|
346
|
+
"datetime",
|
347
|
+
"time",
|
348
|
+
"pathlib",
|
349
|
+
"typing",
|
350
|
+
"collections",
|
351
|
+
"itertools",
|
352
|
+
"functools",
|
353
|
+
"operator",
|
354
|
+
"math",
|
355
|
+
"random",
|
356
|
+
"uuid",
|
357
|
+
"urllib",
|
358
|
+
"http",
|
359
|
+
"html",
|
360
|
+
"xml",
|
361
|
+
"email",
|
362
|
+
"csv",
|
363
|
+
"sqlite3",
|
364
|
+
"subprocess",
|
365
|
+
"threading",
|
366
|
+
"multiprocessing",
|
367
|
+
"asyncio",
|
368
|
+
"contextlib",
|
369
|
+
"dataclasses",
|
370
|
+
"enum",
|
371
|
+
"abc",
|
372
|
+
"io",
|
373
|
+
"tempfile",
|
374
|
+
"shutil",
|
375
|
+
"glob",
|
376
|
+
"pickle",
|
377
|
+
"copy",
|
378
|
+
"heapq",
|
379
|
+
"bisect",
|
380
|
+
"array",
|
381
|
+
"struct",
|
382
|
+
"zlib",
|
383
|
+
"hashlib",
|
384
|
+
"hmac",
|
385
|
+
"secrets",
|
386
|
+
"base64",
|
387
|
+
"binascii",
|
388
|
+
"codecs",
|
389
|
+
"locale",
|
390
|
+
"platform",
|
391
|
+
"socket",
|
392
|
+
"ssl",
|
393
|
+
"ipaddress",
|
394
|
+
"logging",
|
395
|
+
"warnings",
|
396
|
+
"inspect",
|
397
|
+
"ast",
|
398
|
+
"dis",
|
399
|
+
"tokenize",
|
400
|
+
"keyword",
|
401
|
+
"linecache",
|
402
|
+
"traceback",
|
403
|
+
"weakref",
|
404
|
+
"gc",
|
405
|
+
"ctypes",
|
406
|
+
"unittest",
|
407
|
+
"doctest",
|
408
|
+
"pdb",
|
409
|
+
"profile",
|
410
|
+
"cProfile",
|
411
|
+
"timeit",
|
412
|
+
"trace",
|
413
|
+
"calendar",
|
414
|
+
"decimal",
|
415
|
+
"fractions",
|
416
|
+
"statistics",
|
417
|
+
"tomllib",
|
418
|
+
}
|
419
|
+
return module in stdlib_modules
|
420
|
+
|
421
|
+
def _is_local_import(self, stripped_line: str) -> bool:
|
422
|
+
return stripped_line.startswith("from .") or " . " in stripped_line
|
423
|
+
|
312
424
|
def _is_function_end(
|
313
425
|
self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
|
314
426
|
) -> bool:
|
@@ -325,13 +437,44 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
325
437
|
lines: list[str],
|
326
438
|
cleaned_lines: list[str],
|
327
439
|
function_tracker: dict[str, t.Any],
|
440
|
+
import_tracker: dict[str, t.Any],
|
328
441
|
) -> bool:
|
329
442
|
if line_idx > 0 and cleaned_lines and (not cleaned_lines[-1]):
|
330
443
|
return True
|
444
|
+
|
445
|
+
if self._is_import_section_separator(line_idx, lines, import_tracker):
|
446
|
+
return False
|
447
|
+
|
331
448
|
if function_tracker["in_function"]:
|
332
449
|
return self._should_skip_function_empty_line(line_idx, lines)
|
333
450
|
return False
|
334
451
|
|
452
|
+
def _is_import_section_separator(
|
453
|
+
self, line_idx: int, lines: list[str], import_tracker: dict[str, t.Any]
|
454
|
+
) -> bool:
|
455
|
+
if not import_tracker["in_imports"]:
|
456
|
+
return False
|
457
|
+
|
458
|
+
next_line_idx = line_idx + 1
|
459
|
+
while next_line_idx < len(lines) and not lines[next_line_idx].strip():
|
460
|
+
next_line_idx += 1
|
461
|
+
|
462
|
+
if next_line_idx >= len(lines):
|
463
|
+
return False
|
464
|
+
|
465
|
+
next_line = lines[next_line_idx].strip()
|
466
|
+
if not next_line.startswith(("import ", "from ")):
|
467
|
+
return False
|
468
|
+
|
469
|
+
if self._is_stdlib_import(next_line):
|
470
|
+
next_type = "stdlib"
|
471
|
+
elif self._is_local_import(next_line):
|
472
|
+
next_type = "local"
|
473
|
+
else:
|
474
|
+
next_type = "third_party"
|
475
|
+
|
476
|
+
return import_tracker["last_import_type"] != next_type
|
477
|
+
|
335
478
|
def _should_skip_function_empty_line(self, line_idx: int, lines: list[str]) -> bool:
|
336
479
|
next_line_idx = line_idx + 1
|
337
480
|
if next_line_idx >= len(lines):
|
@@ -2,6 +2,7 @@ import time
|
|
2
2
|
import typing as t
|
3
3
|
from enum import Enum, auto
|
4
4
|
from pathlib import Path
|
5
|
+
|
5
6
|
from rich.box import ROUNDED
|
6
7
|
from rich.console import Console
|
7
8
|
from rich.layout import Layout
|
@@ -18,6 +19,7 @@ from rich.prompt import Confirm, Prompt
|
|
18
19
|
from rich.table import Table
|
19
20
|
from rich.text import Text
|
20
21
|
from rich.tree import Tree
|
22
|
+
|
21
23
|
from .errors import CrackerjackError, ErrorCode, handle_error
|
22
24
|
|
23
25
|
|
@@ -6,6 +6,7 @@ from dataclasses import dataclass
|
|
6
6
|
from enum import Enum
|
7
7
|
from pathlib import Path
|
8
8
|
from unittest.mock import MagicMock, patch
|
9
|
+
|
9
10
|
import pytest
|
10
11
|
from rich.console import Console
|
11
12
|
from crackerjack.crackerjack import (
|
@@ -1067,6 +1068,7 @@ class TestCrackerjackProcess:
|
|
1067
1068
|
|
1068
1069
|
def test_code_cleaner_remove_docstrings(self) -> None:
|
1069
1070
|
import ast
|
1071
|
+
|
1070
1072
|
from rich.console import Console
|
1071
1073
|
from crackerjack.crackerjack import CodeCleaner
|
1072
1074
|
|
@@ -1093,6 +1095,7 @@ class TestCrackerjackProcess:
|
|
1093
1095
|
|
1094
1096
|
def test_code_cleaner_remove_docstrings_empty_functions(self) -> None:
|
1095
1097
|
import ast
|
1098
|
+
|
1096
1099
|
from rich.console import Console
|
1097
1100
|
from crackerjack.crackerjack import CodeCleaner
|
1098
1101
|
|
@@ -1124,6 +1127,7 @@ class TestClass:
|
|
1124
1127
|
|
1125
1128
|
def test_code_cleaner_remove_line_comments(self) -> None:
|
1126
1129
|
from pathlib import Path
|
1130
|
+
|
1127
1131
|
from rich.console import Console
|
1128
1132
|
from crackerjack.crackerjack import CodeCleaner
|
1129
1133
|
|
@@ -2,6 +2,7 @@ import tempfile
|
|
2
2
|
import typing as t
|
3
3
|
from pathlib import Path
|
4
4
|
from unittest.mock import MagicMock, patch
|
5
|
+
|
5
6
|
import pytest
|
6
7
|
from rich.console import Console
|
7
8
|
from crackerjack import create_crackerjack_runner
|
@@ -12,7 +13,6 @@ class MockOptions:
|
|
12
13
|
def __init__(self, **kwargs: t.Any) -> None:
|
13
14
|
self.commit = kwargs.get("commit", False)
|
14
15
|
self.interactive = kwargs.get("interactive", False)
|
15
|
-
self.doc = kwargs.get("doc", False)
|
16
16
|
self.no_config_updates = kwargs.get("no_config_updates", False)
|
17
17
|
self.verbose = kwargs.get("verbose", False)
|
18
18
|
self.update_precommit = kwargs.get("update_precommit", False)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import typing as t
|
2
2
|
from unittest.mock import MagicMock, patch
|
3
|
+
|
3
4
|
import pytest
|
4
5
|
from typer.testing import CliRunner
|
5
6
|
from crackerjack.__main__ import BumpOption, Options, app
|
@@ -26,7 +27,6 @@ def test_no_options(runner: CliRunner, mock_crackerjack_process: MagicMock) -> N
|
|
26
27
|
assert isinstance(options, Options)
|
27
28
|
assert not options.commit
|
28
29
|
assert not options.interactive
|
29
|
-
assert not options.doc
|
30
30
|
assert not options.update_precommit
|
31
31
|
assert not options.no_config_updates
|
32
32
|
assert options.publish is None
|
@@ -65,19 +65,6 @@ def test_interactive_option(
|
|
65
65
|
mock_crackerjack_process.process.assert_not_called()
|
66
66
|
|
67
67
|
|
68
|
-
def test_doc_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
|
69
|
-
result = runner.invoke(app, ["-d"])
|
70
|
-
assert result.exit_code == 0
|
71
|
-
mock_crackerjack_process.process.assert_called_once()
|
72
|
-
options = mock_crackerjack_process.process.call_args[0][0]
|
73
|
-
assert options.doc
|
74
|
-
mock_crackerjack_process.process.reset_mock()
|
75
|
-
result = runner.invoke(app, ["--doc"])
|
76
|
-
assert result.exit_code == 0
|
77
|
-
options = mock_crackerjack_process.process.call_args[0][0]
|
78
|
-
assert options.doc
|
79
|
-
|
80
|
-
|
81
68
|
def test_update_precommit_option(
|
82
69
|
runner: CliRunner, mock_crackerjack_process: MagicMock
|
83
70
|
) -> None:
|
@@ -197,17 +184,16 @@ def test_multiple_options(
|
|
197
184
|
runner: CliRunner, mock_crackerjack_process: MagicMock
|
198
185
|
) -> None:
|
199
186
|
with patch("crackerjack.interactive.launch_interactive_cli") as mock_interactive:
|
200
|
-
result = runner.invoke(app, ["-c", "-i", "-
|
187
|
+
result = runner.invoke(app, ["-c", "-i", "-t", "-x"])
|
201
188
|
assert result.exit_code == 0
|
202
189
|
mock_interactive.assert_called_once()
|
203
190
|
mock_crackerjack_process.process.assert_not_called()
|
204
|
-
result = runner.invoke(app, ["-c", "-
|
191
|
+
result = runner.invoke(app, ["-c", "-t", "-x"])
|
205
192
|
assert result.exit_code == 0
|
206
193
|
mock_crackerjack_process.process.assert_called_once()
|
207
194
|
options = mock_crackerjack_process.process.call_args[0][0]
|
208
195
|
assert options.commit
|
209
196
|
assert not options.interactive
|
210
|
-
assert options.doc
|
211
197
|
assert options.test
|
212
198
|
assert options.clean
|
213
199
|
|
@@ -216,7 +202,6 @@ def test_create_options() -> None:
|
|
216
202
|
test_options = Options(
|
217
203
|
commit=True,
|
218
204
|
interactive=True,
|
219
|
-
doc=True,
|
220
205
|
no_config_updates=True,
|
221
206
|
update_precommit=True,
|
222
207
|
verbose=True,
|
@@ -230,7 +215,6 @@ def test_create_options() -> None:
|
|
230
215
|
)
|
231
216
|
assert test_options.commit
|
232
217
|
assert test_options.interactive
|
233
|
-
assert test_options.doc
|
234
218
|
assert test_options.no_config_updates
|
235
219
|
assert test_options.update_precommit
|
236
220
|
assert test_options.verbose
|
Binary file
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.11/3256171999636029978
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.4/10355199064880463147
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.6/15140459877605758699
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.1.9/17041001205004563469
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.11/18187162184424859798
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/16869036553936192448
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/1867267426380906393
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/4240757255861806333
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.12/4441409093023629623
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.13/1867267426380906393
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.13/4240757255861806333
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.2/4070660268492669020
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.3/9818742842212983150
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.4/9818742842212983150
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.6/3557596832929915217
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.7/10386934055395314831
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.11.7/3557596832929915217
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.12.0/5056746222905752453
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.2.0/10047773857155985907
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.2.2/18053836298936336950
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.0/12548816621480535786
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.3/11081883392474770722
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.3.5/16311176246009842383
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.0/11982804814124138945
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.6.0/12055761203849489982
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.7.3/16061516852537040135
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.8.4/16354268377385700367
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.10/12813592349865671909
RENAMED
File without changes
|
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.3/13948373885254993391
RENAMED
File without changes
|
{crackerjack-0.21.7 → crackerjack-0.22.0}/crackerjack/.ruff_cache/0.9.9/12813592349865671909
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|