crackerjack 0.25.0__tar.gz → 0.26.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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (44) hide show
  1. {crackerjack-0.25.0 → crackerjack-0.26.0}/.pre-commit-config-ai.yaml +7 -0
  2. {crackerjack-0.25.0 → crackerjack-0.26.0}/.pre-commit-config.yaml +8 -1
  3. {crackerjack-0.25.0 → crackerjack-0.26.0}/CLAUDE.md +111 -34
  4. {crackerjack-0.25.0 → crackerjack-0.26.0}/PKG-INFO +187 -128
  5. {crackerjack-0.25.0 → crackerjack-0.26.0}/README-AI-AGENT.md +29 -20
  6. {crackerjack-0.25.0 → crackerjack-0.26.0}/README.md +185 -127
  7. {crackerjack-0.25.0 → crackerjack-0.26.0}/RULES.md +21 -0
  8. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/.pre-commit-config-ai.yaml +7 -0
  9. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/.pre-commit-config.yaml +8 -1
  10. {crackerjack-0.25.0 → crackerjack-0.26.0/crackerjack}/pyproject.toml +3 -0
  11. {crackerjack-0.25.0/crackerjack → crackerjack-0.26.0}/pyproject.toml +4 -1
  12. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/TESTING.md +17 -17
  13. {crackerjack-0.25.0 → crackerjack-0.26.0}/uv.lock +45 -22
  14. {crackerjack-0.25.0 → crackerjack-0.26.0}/.envrc +0 -0
  15. {crackerjack-0.25.0 → crackerjack-0.26.0}/.github/FUNDING.yml +0 -0
  16. {crackerjack-0.25.0 → crackerjack-0.26.0}/.gitignore +0 -0
  17. {crackerjack-0.25.0 → crackerjack-0.26.0}/.libcst.codemod.yaml +0 -0
  18. {crackerjack-0.25.0 → crackerjack-0.26.0}/LICENSE +0 -0
  19. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/.gitignore +0 -0
  20. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/.libcst.codemod.yaml +0 -0
  21. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/.pdm.toml +0 -0
  22. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/__init__.py +0 -0
  23. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/__main__.py +0 -0
  24. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/crackerjack.py +0 -0
  25. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/errors.py +0 -0
  26. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/interactive.py +0 -0
  27. {crackerjack-0.25.0 → crackerjack-0.26.0}/crackerjack/py313.py +0 -0
  28. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/__init__.py +0 -0
  29. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/conftest.py +0 -0
  30. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/data/comments_sample.txt +0 -0
  31. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/data/docstrings_sample.txt +0 -0
  32. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/data/expected_comments_sample.txt +0 -0
  33. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/data/init.py +0 -0
  34. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_crackerjack.py +0 -0
  35. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_crackerjack_runner.py +0 -0
  36. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_errors.py +0 -0
  37. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_interactive.py +0 -0
  38. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_interactive_run.py +0 -0
  39. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_main.py +0 -0
  40. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_multiline_functions.py +0 -0
  41. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_py313_advanced.py +0 -0
  42. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_py313_features.py +0 -0
  43. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_pytest_features.py +0 -0
  44. {crackerjack-0.25.0 → crackerjack-0.26.0}/tests/test_structured_errors.py +0 -0
@@ -66,6 +66,13 @@ repos:
66
66
  - id: ruff-format
67
67
  verbose: true
68
68
 
69
+ - repo: https://github.com/executablebooks/mdformat
70
+ rev: 0.7.18
71
+ hooks:
72
+ - id: mdformat
73
+ additional_dependencies:
74
+ - mdformat-ruff
75
+
69
76
  # Code quality tier 2 - analysis
70
77
  - repo: https://github.com/jendrikseipp/vulture
71
78
  rev: 'v2.14'
@@ -22,7 +22,7 @@ repos:
22
22
 
23
23
  # Package management - once structure is valid
24
24
  - repo: https://github.com/astral-sh/uv-pre-commit
25
- rev: 0.7.20
25
+ rev: 0.7.21
26
26
  hooks:
27
27
  - id: uv-lock
28
28
  files: ^pyproject\.toml$
@@ -48,6 +48,13 @@ repos:
48
48
  - id: ruff-check
49
49
  - id: ruff-format
50
50
 
51
+ - repo: https://github.com/executablebooks/mdformat
52
+ rev: 0.7.22
53
+ hooks:
54
+ - id: mdformat
55
+ additional_dependencies:
56
+ - mdformat-ruff
57
+
51
58
  # Code quality tier 2 - analysis
52
59
  - repo: https://github.com/jendrikseipp/vulture
53
60
  rev: 'v2.14'
@@ -124,6 +124,7 @@ Crackerjack is designed with modern Python principles and consists of several ke
124
124
  ### Core Components
125
125
 
126
126
  1. **Crackerjack** (`crackerjack.py`): Main class that orchestrates the entire workflow
127
+
127
128
  - Manages configuration updates
128
129
  - Runs pre-commit hooks
129
130
  - Handles code cleaning (with enhanced error handling)
@@ -132,25 +133,29 @@ Crackerjack is designed with modern Python principles and consists of several ke
132
133
  - Handles Git operations
133
134
  - Integrates with Rich console for status output
134
135
 
135
- 2. **CodeCleaner**: Responsible for cleaning code
136
+ 1. **CodeCleaner**: Responsible for cleaning code
137
+
136
138
  - Removes docstrings (with syntax-aware pass statement insertion)
137
139
  - Removes line comments
138
140
  - Removes extra whitespace
139
141
  - Reformats code using Ruff
140
142
  - Handles file encoding issues gracefully
141
143
 
142
- 3. **ConfigManager**: Handles configuration file management
144
+ 1. **ConfigManager**: Handles configuration file management
145
+
143
146
  - Updates pyproject.toml settings
144
147
  - Manages configuration files (.gitignore, .pre-commit-config.yaml)
145
148
  - Supports dynamic configuration based on project size
146
149
 
147
- 4. **ProjectManager**: Manages project-level operations
150
+ 1. **ProjectManager**: Manages project-level operations
151
+
148
152
  - Runs pre-commit hooks
149
153
  - Updates package configurations
150
154
  - Runs interactive hooks
151
155
  - Detects project size for optimization
152
156
 
153
- 5. **ErrorHandler** (`errors.py`): Structured error handling system
157
+ 1. **ErrorHandler** (`errors.py`): Structured error handling system
158
+
154
159
  - Provides consistent error codes and messages
155
160
  - Handles graceful degradation on failures
156
161
  - Supports both fatal and non-fatal error patterns
@@ -186,14 +191,15 @@ Crackerjack includes a Rich-based interactive UI that provides:
186
191
  - **Task Dependencies**: Visual display of task relationships and execution order
187
192
 
188
193
  The interactive mode runs a predefined workflow with tasks:
194
+
189
195
  1. **Setup** - Initialize project structure
190
- 2. **Config** - Update configuration files
191
- 3. **Clean** - Remove docstrings and comments
192
- 4. **Hooks** - Run pre-commit hooks
193
- 5. **Test** - Execute test suite
194
- 6. **Version** - Bump version numbers
195
- 7. **Publish** - Publish to PyPI
196
- 8. **Commit** - Commit changes to Git
196
+ 1. **Config** - Update configuration files
197
+ 1. **Clean** - Remove docstrings and comments
198
+ 1. **Hooks** - Run pre-commit hooks
199
+ 1. **Test** - Execute test suite
200
+ 1. **Version** - Bump version numbers
201
+ 1. **Publish** - Publish to PyPI
202
+ 1. **Commit** - Commit changes to Git
197
203
 
198
204
  Access interactive mode with: `python -m crackerjack -i`
199
205
 
@@ -202,6 +208,7 @@ Access interactive mode with: `python -m crackerjack -i`
202
208
  Crackerjack follows a single-file architecture for simplicity and maintainability:
203
209
 
204
210
  ### File Structure
211
+
205
212
  - `crackerjack.py` - Main module (~3000 lines) containing all core functionality
206
213
  - `errors.py` - Structured error handling system
207
214
  - `interactive.py` - Rich-based interactive UI implementation
@@ -209,6 +216,7 @@ Crackerjack follows a single-file architecture for simplicity and maintainabilit
209
216
  - `__main__.py` - Entry point for `python -m crackerjack`
210
217
 
211
218
  ### Key Implementation Details
219
+
212
220
  - **Single-file Design**: Most functionality concentrated in `crackerjack.py` for easier maintenance
213
221
  - **Type Safety**: Extensive use of protocols and type hints throughout
214
222
  - **Error Handling**: Comprehensive error handling with structured error codes
@@ -253,6 +261,7 @@ Crackerjack follows a single-file architecture for simplicity and maintainabilit
253
261
  ## Development Guidelines
254
262
 
255
263
  1. **Code Style**: Follow the Crackerjack style guide (see RULES.md):
264
+
256
265
  - **Target Python 3.13+** - Use latest Python features
257
266
  - Use static typing throughout with modern syntax (import typing as `t`)
258
267
  - Use pathlib for file operations
@@ -260,7 +269,8 @@ Crackerjack follows a single-file architecture for simplicity and maintainabilit
260
269
  - Use built-in collection types (`list[str]`, `dict[str, int]`) instead of typing equivalents
261
270
  - Leverage Python 3.13+ performance and language improvements
262
271
 
263
- 2. **Testing Approach**:
272
+ 1. **Testing Approach**:
273
+
264
274
  - Write unit tests for all functionality
265
275
  - Add benchmark tests for performance-critical code
266
276
  - Tests are run in parallel by default
@@ -268,18 +278,21 @@ Crackerjack follows a single-file architecture for simplicity and maintainabilit
268
278
  - Use pytest's `tmp_path` and `tmp_path_factory` fixtures
269
279
  - Tests should be isolated and not affect the surrounding environment
270
280
 
271
- 3. **Dependencies**:
281
+ 1. **Dependencies**:
282
+
272
283
  - UV for dependency management and tool execution
273
284
  - Ruff for linting and formatting
274
285
  - Pytest for testing
275
286
  - All tools should be run through UV for environment isolation
276
287
 
277
- 4. **Python Version**:
288
+ 1. **Python Version**:
289
+
278
290
  - **Target: Python 3.13+** - Crackerjack requires Python 3.13 or newer
279
291
  - Use modern Python 3.13+ features and syntax
280
292
  - Code must be compatible with Python 3.13+ only
281
293
 
282
- 5. **Version Management**:
294
+ 1. **Version Management**:
295
+
283
296
  - Version bumping is handled through UV
284
297
  - Follows semantic versioning
285
298
 
@@ -292,6 +305,7 @@ When generating code, AI assistants MUST follow these standards to ensure compli
292
305
  ### Refurb Standards (Modern Python Patterns up to 3.12)
293
306
 
294
307
  **Use modern syntax and built-ins:**
308
+
295
309
  - Use `pathlib.Path` instead of `os.path` operations
296
310
  - Use `str.removeprefix()` and `str.removesuffix()` instead of string slicing
297
311
  - Use `itertools.batched()` for chunking sequences (Python 3.12+)
@@ -300,20 +314,24 @@ When generating code, AI assistants MUST follow these standards to ensure compli
300
314
  - Use `dict1 | dict2` for merging instead of `{**dict1, **dict2}`
301
315
 
302
316
  **Use efficient built-in functions:**
317
+
303
318
  - Use `any()` and `all()` instead of manual boolean loops
304
319
  - Use list/dict comprehensions over manual loops when appropriate
305
320
  - Use `enumerate()` instead of manual indexing with `range(len())`
306
321
  - Use `zip()` for parallel iteration instead of manual indexing
307
322
 
308
323
  **Resource management:**
324
+
309
325
  - Always use context managers (`with` statements) for file operations
310
326
  - Use `tempfile` module for temporary files instead of manual paths
311
327
  - Prefer `subprocess.run()` over `subprocess.Popen()` when possible
312
328
 
313
329
  **Example of good patterns:**
330
+
314
331
  ```python
315
332
  # Good: Modern pathlib usage
316
333
  from pathlib import Path
334
+
317
335
  config_file = Path("config") / "settings.yaml"
318
336
  if config_file.exists():
319
337
  content = config_file.read_text(encoding="utf-8")
@@ -322,10 +340,12 @@ if config_file.exists():
322
340
  if name.startswith("test_"):
323
341
  name = name.removeprefix("test_")
324
342
 
343
+
325
344
  # Good: Union types (Python 3.13+)
326
345
  def process_data(data: str | bytes) -> dict[str, Any]:
327
346
  pass
328
347
 
348
+
329
349
  # Good: Context managers
330
350
  with open(file_path, encoding="utf-8") as f:
331
351
  data = f.read()
@@ -334,46 +354,55 @@ with open(file_path, encoding="utf-8") as f:
334
354
  ### Bandit Security Standards
335
355
 
336
356
  **Never use dangerous functions:**
357
+
337
358
  - Avoid `eval()`, `exec()`, or `compile()` with any user input
338
359
  - Never use `subprocess.shell=True` or `os.system()`
339
360
  - Don't use `pickle` with untrusted data
340
361
  - Avoid `yaml.load()` - use `yaml.safe_load()` instead
341
362
 
342
363
  **Cryptography and secrets:**
364
+
343
365
  - Use `secrets` module for cryptographic operations, never `random`
344
366
  - Never hardcode passwords, API keys, or secrets in source code
345
367
  - Use environment variables or secure configuration for sensitive data
346
368
  - Use `hashlib` with explicit algorithms, avoid MD5/SHA1 for security
347
369
 
348
370
  **File and path security:**
371
+
349
372
  - Always validate file paths to prevent directory traversal
350
373
  - Use `tempfile.mkstemp()` instead of predictable temporary file names
351
374
  - Always specify encoding when opening files
352
375
  - Validate all external inputs before processing
353
376
 
354
377
  **Database and injection prevention:**
378
+
355
379
  - Use parameterized queries, never string concatenation for SQL
356
380
  - Validate and sanitize all user inputs
357
381
  - Use prepared statements for database operations
358
382
 
359
383
  **Example of secure patterns:**
384
+
360
385
  ```python
361
386
  # Good: Secure random generation
362
387
  import secrets
388
+
363
389
  token = secrets.token_urlsafe(32)
364
390
 
365
391
  # Good: Safe subprocess usage
366
392
  import subprocess
393
+
367
394
  result = subprocess.run(["ls", "-la"], capture_output=True, text=True)
368
395
 
369
396
  # Good: Secure file operations
370
397
  import tempfile
371
- with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', delete=False) as f:
398
+
399
+ with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) as f:
372
400
  f.write(data)
373
401
  temp_path = f.name
374
402
 
375
403
  # Good: Environment variables for secrets
376
404
  import os
405
+
377
406
  api_key = os.environ.get("API_KEY")
378
407
  if not api_key:
379
408
  raise ValueError("API_KEY environment variable required")
@@ -385,39 +414,46 @@ cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
385
414
  ### Pyright Type Safety Standards
386
415
 
387
416
  **Always use explicit type annotations:**
417
+
388
418
  - Function parameters must have type hints
389
419
  - Function return types must be annotated
390
420
  - Class attributes should have type annotations
391
421
  - Use `from __future__ import annotations` for forward references
392
422
 
393
423
  **Handle Optional types properly:**
424
+
394
425
  - Use `str | None` instead of `Optional[str]` (required for Python 3.13+)
395
426
  - Always check for None before using optional values
396
427
  - Use explicit `assert` statements or type guards when narrowing types
397
428
 
398
429
  **Generic types and collections:**
430
+
399
431
  - Use `list[str]` instead of `List[str]` (required for Python 3.13+)
400
432
  - Use `dict[str, Any]` instead of `Dict[str, Any]` (required for Python 3.13+)
401
433
  - Properly type generic classes with `TypeVar` when needed
402
434
  - Use `Sequence` or `Iterable` for function parameters when appropriate
403
435
 
404
436
  **Protocol and ABC usage:**
437
+
405
438
  - Prefer `typing.Protocol` over abstract base classes for duck typing
406
439
  - Use `@runtime_checkable` when protocols need runtime checks
407
440
  - Define clear interfaces with protocols
408
441
 
409
442
  **Python 3.13+ specific features:**
443
+
410
444
  - Leverage improved error messages and performance optimizations
411
445
  - Use enhanced type system features available in 3.13+
412
446
  - Take advantage of improved pathlib and asyncio features
413
447
  - Use any new syntax or standard library improvements
414
448
 
415
449
  **Import and module organization:**
450
+
416
451
  - Import types in TYPE_CHECKING blocks when needed for forward references
417
452
  - Use proper module-level `__all__` declarations
418
453
  - Organize imports: standard library, third-party, local imports
419
454
 
420
455
  **Example of proper typing:**
456
+
421
457
  ```python
422
458
  from __future__ import annotations
423
459
 
@@ -427,10 +463,12 @@ from pathlib import Path
427
463
  if TYPE_CHECKING:
428
464
  from collections.abc import Sequence
429
465
 
466
+
430
467
  @runtime_checkable
431
468
  class Writable(Protocol):
432
469
  def write(self, data: str) -> None: ...
433
470
 
471
+
434
472
  def process_files(
435
473
  paths: Sequence[Path],
436
474
  output: Writable,
@@ -447,6 +485,7 @@ def process_files(
447
485
 
448
486
  return stats
449
487
 
488
+
450
489
  # Good: Type narrowing with assertion
451
490
  def validate_config(config: dict[str, str | None]) -> dict[str, str]:
452
491
  """Validate that all config values are non-None."""
@@ -460,6 +499,7 @@ def validate_config(config: dict[str, str | None]) -> dict[str, str]:
460
499
  ### Integration with Pre-commit Hooks
461
500
 
462
501
  These standards align with the project's pre-commit hooks:
502
+
463
503
  - **Refurb**: Automatically suggests modern Python patterns
464
504
  - **Bandit**: Scans for security vulnerabilities
465
505
  - **Pyright**: Enforces type safety
@@ -480,13 +520,16 @@ By following these guidelines during code generation, AI assistants will produce
480
520
  ### CodeCleaner Docstring Removal Fix (December 2024)
481
521
 
482
522
  #### Problem Description
523
+
483
524
  The original `remove_docstrings` method in the `CodeCleaner` class had a critical bug where removing docstrings from functions or methods that contained only docstrings would result in syntactically invalid Python code. This caused the `-x` (clean) flag to fail with Ruff formatting errors.
484
525
 
485
526
  **Example of problematic code:**
527
+
486
528
  ```python
487
529
  def empty_function():
488
530
  """This function has only a docstring."""
489
531
 
532
+
490
533
  class TestClass:
491
534
  """Class docstring."""
492
535
 
@@ -495,78 +538,95 @@ class TestClass:
495
538
  ```
496
539
 
497
540
  **After broken docstring removal:**
541
+
498
542
  ```python
499
543
  def empty_function():
544
+ pass
545
+
500
546
 
501
547
  class TestClass:
548
+ pass
502
549
 
503
550
  def method_with_docstring_only(self):
551
+ pass
504
552
  ```
505
553
 
506
554
  This resulted in syntax errors: `expected an indented block after function definition`.
507
555
 
508
556
  #### Root Cause Analysis
557
+
509
558
  The issue occurred because the original algorithm:
559
+
510
560
  1. Removed docstrings without checking if they were the only content in function/method bodies
511
- 2. Did not track function indentation levels
512
- 3. Failed to detect when `pass` statements were needed to maintain valid Python syntax
513
- 4. Had a bug in `_handle_docstring_end` that returned `True` instead of `False`
561
+ 1. Did not track function indentation levels
562
+ 1. Failed to detect when `pass` statements were needed to maintain valid Python syntax
563
+ 1. Had a bug in `_handle_docstring_end` that returned `True` instead of `False`
514
564
 
515
565
  #### Solution Implementation
566
+
516
567
  The fix involved a comprehensive rewrite of the docstring removal algorithm with these enhancements:
517
568
 
518
569
  1. **Function Context Tracking**: Added `function_indent` and `removed_docstring` to track the context of function/class definitions
519
- 2. **Lookahead Logic**: Implemented `_needs_pass_statement()` helper method that analyzes remaining code to determine if a `pass` statement is needed
520
- 3. **Automatic Pass Insertion**: Added logic to insert properly indented `pass` statements when removing docstrings leaves empty function bodies
521
- 4. **Single vs Multi-line Handling**: Enhanced handling for both single-line and multi-line docstrings
522
- 5. **Bug Fixes**: Fixed the `_handle_docstring_end` method to return correct boolean values
570
+ 1. **Lookahead Logic**: Implemented `_needs_pass_statement()` helper method that analyzes remaining code to determine if a `pass` statement is needed
571
+ 1. **Automatic Pass Insertion**: Added logic to insert properly indented `pass` statements when removing docstrings leaves empty function bodies
572
+ 1. **Single vs Multi-line Handling**: Enhanced handling for both single-line and multi-line docstrings
573
+ 1. **Bug Fixes**: Fixed the `_handle_docstring_end` method to return correct boolean values
523
574
 
524
575
  #### Key Changes Made
525
576
 
526
577
  **Enhanced State Management:**
578
+
527
579
  ```python
528
580
  docstring_state = {
529
581
  "in_docstring": False,
530
582
  "delimiter": None,
531
583
  "waiting": False,
532
- "function_indent": 0, # NEW: Track function indentation
533
- "removed_docstring": False # NEW: Track if we just removed a docstring
584
+ "function_indent": 0, # NEW: Track function indentation
585
+ "removed_docstring": False, # NEW: Track if we just removed a docstring
534
586
  }
535
587
  ```
536
588
 
537
589
  **New Helper Method:**
590
+
538
591
  ```python
539
- def _needs_pass_statement(self, lines: list[str], start_index: int, function_indent: int) -> bool:
592
+ def _needs_pass_statement(
593
+ self, lines: list[str], start_index: int, function_indent: int
594
+ ) -> bool:
540
595
  """Check if we need to add a pass statement after removing a docstring."""
541
596
  # Looks ahead to see if there are any statements at the correct indentation level
542
597
  # Returns True if no statements found (pass needed), False if statements exist
543
598
  ```
544
599
 
545
600
  **Enhanced Docstring Removal Logic:**
601
+
546
602
  - For single-line docstrings: Check immediately if pass statement needed
547
603
  - For multi-line docstrings: Check after docstring end is reached
548
604
  - Proper indentation calculation: `function_indent + 4` spaces for pass statements
549
605
  - Context-aware pass insertion that respects Python indentation rules
550
606
 
551
607
  #### Testing Enhancements
608
+
552
609
  Added comprehensive tests to prevent regression:
553
610
 
554
611
  1. **Enhanced Existing Test**: Added AST parsing validation to `test_code_cleaner_remove_docstrings`
555
- 2. **New Comprehensive Test**: Created `test_code_cleaner_remove_docstrings_empty_functions` that specifically tests:
612
+ 1. **New Comprehensive Test**: Created `test_code_cleaner_remove_docstrings_empty_functions` that specifically tests:
556
613
  - Functions with only docstrings get `pass` statements
557
614
  - Functions with code after docstrings don't get unnecessary `pass` statements
558
615
  - Classes with only docstrings are handled correctly
559
616
  - All resulting code is syntactically valid Python
560
617
 
561
618
  #### Test Cases Covered
619
+
562
620
  ```python
563
621
  # Test cases that now pass:
564
622
  def empty_function():
565
623
  """This function has only a docstring."""
566
624
  # Becomes: def empty_function():\n pass
567
625
 
626
+
568
627
  class TestClass:
569
628
  """Class docstring."""
629
+
570
630
  # Becomes: class TestClass:\n (no pass needed for classes)
571
631
 
572
632
  def method_with_docstring_only(self):
@@ -580,6 +640,7 @@ class TestClass:
580
640
  ```
581
641
 
582
642
  #### Impact and Benefits
643
+
583
644
  - **Immediate Fix**: The `-x` flag now works without causing syntax errors
584
645
  - **Robust Solution**: Handles all edge cases including nested functions, mixed indentation, and various docstring styles
585
646
  - **Maintains Functionality**: All existing docstring removal capabilities preserved
@@ -587,13 +648,16 @@ class TestClass:
587
648
  - **Performance**: Minimal performance impact due to efficient lookahead algorithm
588
649
 
589
650
  #### Backward Compatibility
651
+
590
652
  This fix is fully backward compatible:
653
+
591
654
  - All existing functionality is preserved
592
655
  - No breaking changes to the API
593
656
  - Existing tests continue to pass
594
657
  - Only adds pass statements where syntactically required
595
658
 
596
659
  #### Files Modified
660
+
597
661
  - `crackerjack/crackerjack.py`: Enhanced `remove_docstrings` method and added `_needs_pass_statement` helper
598
662
  - `tests/test_crackerjack.py`: Added syntax validation and comprehensive test cases
599
663
 
@@ -602,32 +666,37 @@ This fix ensures that the code cleaning functionality (`-x` flag) works reliably
602
666
  ### Enhanced Error Handling (December 2024)
603
667
 
604
668
  #### Problem Description
669
+
605
670
  The original code cleaner had basic error handling but would stop processing if any individual file encountered an error during cleaning. This could prevent the tool from cleaning other files in the project, particularly in cases involving:
671
+
606
672
  - File permission issues
607
673
  - Encoding problems (non-UTF-8 files)
608
674
  - File system errors (file locks, disk space)
609
675
  - Malformed Python code that causes parsing issues
610
676
 
611
677
  #### Solution Implementation
678
+
612
679
  Enhanced the `clean_file` method with comprehensive error handling that:
613
680
 
614
681
  1. **Graceful Degradation**: Each cleaning step (remove comments, remove docstrings, remove whitespace, reformat) is wrapped in individual try-catch blocks
615
- 2. **Step-by-Step Recovery**: If one cleaning step fails, the cleaner falls back to the previous state and continues with remaining steps
616
- 3. **Detailed Error Reporting**: Uses the structured error handling system with specific error codes:
682
+ 1. **Step-by-Step Recovery**: If one cleaning step fails, the cleaner falls back to the previous state and continues with remaining steps
683
+ 1. **Detailed Error Reporting**: Uses the structured error handling system with specific error codes:
617
684
  - `PERMISSION_ERROR (6002)`: File permission issues
618
685
  - `FILE_WRITE_ERROR (6004)`: File system errors
619
686
  - `FILE_READ_ERROR (6003)`: Encoding or read errors
620
687
  - `UNEXPECTED_ERROR (9999)`: Unexpected errors with detailed context
621
- 4. **Non-Fatal Errors**: All errors are handled gracefully without stopping the overall cleaning process (`exit_on_error=False`)
622
- 5. **UTF-8 Encoding**: Explicit UTF-8 encoding for file operations to prevent encoding issues
688
+ 1. **Non-Fatal Errors**: All errors are handled gracefully without stopping the overall cleaning process (`exit_on_error=False`)
689
+ 1. **UTF-8 Encoding**: Explicit UTF-8 encoding for file operations to prevent encoding issues
623
690
 
624
691
  #### Key Improvements
692
+
625
693
  - **Resilient Processing**: The cleaner continues processing other files even if individual files fail
626
694
  - **Clear Diagnostics**: Detailed error messages with recovery suggestions help users understand and fix issues
627
695
  - **Fallback Mechanism**: Each cleaning step can fall back to the original code if specific operations fail
628
696
  - **Step Isolation**: Failure in one cleaning step doesn't prevent other steps from running
629
697
 
630
698
  #### Example Error Handling Flow
699
+
631
700
  ```python
632
701
  try:
633
702
  code = self.remove_line_comments(code)
@@ -643,6 +712,7 @@ except Exception as e:
643
712
  ```
644
713
 
645
714
  #### Benefits
715
+
646
716
  - **Robustness**: Code cleaning continues even when encountering problematic files
647
717
  - **Better User Experience**: Clear error messages with actionable recovery suggestions
648
718
  - **Debugging Support**: Detailed error information helps identify and fix underlying issues
@@ -650,6 +720,7 @@ except Exception as e:
650
720
  - **Project-Wide Cleaning**: Ensures that cleaning doesn't stop due to individual file issues
651
721
 
652
722
  #### Files Modified
723
+
653
724
  - `crackerjack/crackerjack.py`: Enhanced `clean_file` method with comprehensive error handling
654
725
 
655
726
  This enhancement ensures that the code cleaner (`-x` flag) can handle edge cases and problematic files while continuing to process the rest of the project successfully.
@@ -659,14 +730,20 @@ This enhancement ensures that the code cleaner (`-x` flag) can handle edge cases
659
730
  **MANDATORY: Before marking any task as complete, AI assistants MUST:**
660
731
 
661
732
  1. **Run crackerjack verification**: Execute `python -m crackerjack -t --ai-agent` to run all quality checks and tests with AI-optimized output
662
- 2. **Fix any issues found**: Address all formatting, linting, type checking, and test failures
663
- 3. **Re-run verification**: Ensure crackerjack passes completely (all hooks pass, all tests pass)
664
- 4. **Document verification**: Mention that crackerjack verification was completed successfully
733
+ 1. **Fix any issues found**: Address all formatting, linting, type checking, and test failures
734
+ 1. **Re-run verification**: Ensure crackerjack passes completely (all hooks pass, all tests pass)
735
+ 1. **Document verification**: Mention that crackerjack verification was completed successfully
665
736
 
666
737
  **Why this is critical:**
738
+
667
739
  - Ensures all code meets project quality standards
668
740
  - Prevents broken code from being committed
669
741
  - Maintains consistency with project development workflow
670
742
  - Catches issues early before they become problems
671
743
 
672
744
  **Never skip crackerjack verification** - it's the project's standard quality gate.
745
+
746
+ ## Development Memories
747
+
748
+ - Non-critical type errors are still errors that need to be fixed to pass crackerjack validation
749
+ - test directory files need to pass pyright tests as well in order for crackerjack to successfully complete