crackerjack 0.21.7__tar.gz → 0.21.8__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.
Files changed (90) hide show
  1. {crackerjack-0.21.7 → crackerjack-0.21.8}/PKG-INFO +1 -1
  2. crackerjack-0.21.8/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
  3. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/__init__.py +1 -0
  4. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/__main__.py +1 -0
  5. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/crackerjack.py +148 -4
  6. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/errors.py +1 -0
  7. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/interactive.py +2 -0
  8. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/pyproject.toml +1 -1
  9. {crackerjack-0.21.7 → crackerjack-0.21.8}/pyproject.toml +1 -1
  10. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/conftest.py +1 -0
  11. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_crackerjack.py +4 -0
  12. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_crackerjack_runner.py +1 -0
  13. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_errors.py +1 -0
  14. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_interactive.py +1 -0
  15. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_interactive_run.py +1 -0
  16. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_main.py +1 -0
  17. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_multiline_functions.py +1 -0
  18. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_py313_advanced.py +1 -0
  19. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_py313_features.py +1 -0
  20. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_pytest_features.py +1 -0
  21. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/test_structured_errors.py +1 -0
  22. crackerjack-0.21.7/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
  23. {crackerjack-0.21.7 → crackerjack-0.21.8}/LICENSE +0 -0
  24. {crackerjack-0.21.7 → crackerjack-0.21.8}/README.md +0 -0
  25. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.gitignore +0 -0
  26. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.libcst.codemod.yaml +0 -0
  27. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pdm.toml +0 -0
  28. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pre-commit-config-ai.yaml +0 -0
  29. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pre-commit-config.yaml +0 -0
  30. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pytest_cache/.gitignore +0 -0
  31. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pytest_cache/CACHEDIR.TAG +0 -0
  32. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pytest_cache/README.md +0 -0
  33. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pytest_cache/v/cache/nodeids +0 -0
  34. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.pytest_cache/v/cache/stepwise +0 -0
  35. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/.gitignore +0 -0
  36. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  37. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  38. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  39. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  40. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  41. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  42. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.11/18187162184424859798 +0 -0
  43. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.12/16869036553936192448 +0 -0
  44. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.12/1867267426380906393 +0 -0
  45. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.12/4240757255861806333 +0 -0
  46. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.12/4441409093023629623 +0 -0
  47. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.13/1867267426380906393 +0 -0
  48. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.13/4240757255861806333 +0 -0
  49. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  50. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  51. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  52. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  53. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  54. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  55. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  56. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.12.0/5056746222905752453 +0 -0
  57. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  58. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  59. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  60. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  61. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  62. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  63. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  64. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  65. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  66. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  67. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  68. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  69. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  70. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  71. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  72. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  73. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  74. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  75. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  76. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  77. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  78. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  79. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  80. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  81. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  82. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  83. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/.ruff_cache/CACHEDIR.TAG +0 -0
  84. {crackerjack-0.21.7 → crackerjack-0.21.8}/crackerjack/py313.py +0 -0
  85. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/TESTING.md +0 -0
  86. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/__init__.py +0 -0
  87. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/data/comments_sample.txt +0 -0
  88. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/data/docstrings_sample.txt +0 -0
  89. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/data/expected_comments_sample.txt +0 -0
  90. {crackerjack-0.21.7 → crackerjack-0.21.8}/tests/data/init.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crackerjack
3
- Version: 0.21.7
3
+ Version: 0.21.8
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>
@@ -1,4 +1,5 @@
1
1
  import typing as t
2
+
2
3
  from .crackerjack import Crackerjack, create_crackerjack_runner
3
4
  from .errors import (
4
5
  CleaningError,
@@ -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
@@ -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
@@ -169,9 +170,12 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
169
170
  cleaned_lines = []
170
171
  docstring_state = self._initialize_docstring_state()
171
172
  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)
173
+ handled, result_line = self._process_line(lines, i, line, docstring_state)
174
+ if handled:
175
+ if result_line is not None:
176
+ cleaned_lines.append(result_line)
177
+ else:
178
+ cleaned_lines.append(line)
175
179
  return "\n".join(cleaned_lines)
176
180
 
177
181
  def _is_function_or_class_definition(self, stripped_line: str) -> bool:
@@ -287,13 +291,15 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
287
291
  lines = code.split("\n")
288
292
  cleaned_lines = []
289
293
  function_tracker = {"in_function": False, "function_indent": 0}
294
+ import_tracker = {"in_imports": False, "last_import_type": None}
290
295
  for i, line in enumerate(lines):
291
296
  line = line.rstrip()
292
297
  stripped_line = line.lstrip()
293
298
  self._update_function_state(line, stripped_line, function_tracker)
299
+ self._update_import_state(line, stripped_line, import_tracker)
294
300
  if not line:
295
301
  if self._should_skip_empty_line(
296
- i, lines, cleaned_lines, function_tracker
302
+ i, lines, cleaned_lines, function_tracker, import_tracker
297
303
  ):
298
304
  continue
299
305
  cleaned_lines.append(line)
@@ -309,6 +315,113 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
309
315
  function_tracker["in_function"] = False
310
316
  function_tracker["function_indent"] = 0
311
317
 
318
+ def _update_import_state(
319
+ self, line: str, stripped_line: str, import_tracker: dict[str, t.Any]
320
+ ) -> None:
321
+ if stripped_line.startswith(("import ", "from ")):
322
+ import_tracker["in_imports"] = True
323
+ if self._is_stdlib_import(stripped_line):
324
+ current_type = "stdlib"
325
+ elif self._is_local_import(stripped_line):
326
+ current_type = "local"
327
+ else:
328
+ current_type = "third_party"
329
+ import_tracker["last_import_type"] = current_type
330
+ elif stripped_line and not stripped_line.startswith("#"):
331
+ import_tracker["in_imports"] = False
332
+ import_tracker["last_import_type"] = None
333
+
334
+ def _is_stdlib_import(self, stripped_line: str) -> bool:
335
+ try:
336
+ if stripped_line.startswith("from "):
337
+ module = stripped_line.split()[1].split(".")[0]
338
+ else:
339
+ module = stripped_line.split()[1].split(".")[0]
340
+ except IndexError:
341
+ return False
342
+ stdlib_modules = {
343
+ "os",
344
+ "sys",
345
+ "re",
346
+ "json",
347
+ "datetime",
348
+ "time",
349
+ "pathlib",
350
+ "typing",
351
+ "collections",
352
+ "itertools",
353
+ "functools",
354
+ "operator",
355
+ "math",
356
+ "random",
357
+ "uuid",
358
+ "urllib",
359
+ "http",
360
+ "html",
361
+ "xml",
362
+ "email",
363
+ "csv",
364
+ "sqlite3",
365
+ "subprocess",
366
+ "threading",
367
+ "multiprocessing",
368
+ "asyncio",
369
+ "contextlib",
370
+ "dataclasses",
371
+ "enum",
372
+ "abc",
373
+ "io",
374
+ "tempfile",
375
+ "shutil",
376
+ "glob",
377
+ "pickle",
378
+ "copy",
379
+ "heapq",
380
+ "bisect",
381
+ "array",
382
+ "struct",
383
+ "zlib",
384
+ "hashlib",
385
+ "hmac",
386
+ "secrets",
387
+ "base64",
388
+ "binascii",
389
+ "codecs",
390
+ "locale",
391
+ "platform",
392
+ "socket",
393
+ "ssl",
394
+ "ipaddress",
395
+ "logging",
396
+ "warnings",
397
+ "inspect",
398
+ "ast",
399
+ "dis",
400
+ "tokenize",
401
+ "keyword",
402
+ "linecache",
403
+ "traceback",
404
+ "weakref",
405
+ "gc",
406
+ "ctypes",
407
+ "unittest",
408
+ "doctest",
409
+ "pdb",
410
+ "profile",
411
+ "cProfile",
412
+ "timeit",
413
+ "trace",
414
+ "calendar",
415
+ "decimal",
416
+ "fractions",
417
+ "statistics",
418
+ "tomllib",
419
+ }
420
+ return module in stdlib_modules
421
+
422
+ def _is_local_import(self, stripped_line: str) -> bool:
423
+ return stripped_line.startswith("from .") or " . " in stripped_line
424
+
312
425
  def _is_function_end(
313
426
  self, line: str, stripped_line: str, function_tracker: dict[str, t.Any]
314
427
  ) -> bool:
@@ -325,13 +438,44 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
325
438
  lines: list[str],
326
439
  cleaned_lines: list[str],
327
440
  function_tracker: dict[str, t.Any],
441
+ import_tracker: dict[str, t.Any],
328
442
  ) -> bool:
329
443
  if line_idx > 0 and cleaned_lines and (not cleaned_lines[-1]):
330
444
  return True
445
+
446
+ if self._is_import_section_separator(line_idx, lines, import_tracker):
447
+ return False
448
+
331
449
  if function_tracker["in_function"]:
332
450
  return self._should_skip_function_empty_line(line_idx, lines)
333
451
  return False
334
452
 
453
+ def _is_import_section_separator(
454
+ self, line_idx: int, lines: list[str], import_tracker: dict[str, t.Any]
455
+ ) -> bool:
456
+ if not import_tracker["in_imports"]:
457
+ return False
458
+
459
+ next_line_idx = line_idx + 1
460
+ while next_line_idx < len(lines) and not lines[next_line_idx].strip():
461
+ next_line_idx += 1
462
+
463
+ if next_line_idx >= len(lines):
464
+ return False
465
+
466
+ next_line = lines[next_line_idx].strip()
467
+ if not next_line.startswith(("import ", "from ")):
468
+ return False
469
+
470
+ if self._is_stdlib_import(next_line):
471
+ next_type = "stdlib"
472
+ elif self._is_local_import(next_line):
473
+ next_type = "local"
474
+ else:
475
+ next_type = "third_party"
476
+
477
+ return import_tracker["last_import_type"] != next_type
478
+
335
479
  def _should_skip_function_empty_line(self, line_idx: int, lines: list[str]) -> bool:
336
480
  next_line_idx = line_idx + 1
337
481
  if next_line_idx >= len(lines):
@@ -2,6 +2,7 @@ import sys
2
2
  import typing as t
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
+
5
6
  from rich.console import Console
6
7
  from rich.panel import Panel
7
8
 
@@ -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
 
@@ -4,7 +4,7 @@ requires = [ "pdm-backend" ]
4
4
 
5
5
  [project]
6
6
  name = "crackerjack"
7
- version = "0.21.6"
7
+ version = "0.21.7"
8
8
  description = "Crackerjack: code quality toolkit"
9
9
  readme = "README.md"
10
10
  keywords = [
@@ -6,7 +6,7 @@ requires = [
6
6
 
7
7
  [project]
8
8
  name = "crackerjack"
9
- version = "0.21.7"
9
+ version = "0.21.8"
10
10
  description = "Crackerjack: code quality toolkit"
11
11
  readme = "README.md"
12
12
  keywords = [
@@ -2,6 +2,7 @@ import os
2
2
  import time
3
3
  import typing as t
4
4
  from pathlib import Path
5
+
5
6
  import pytest
6
7
  from pytest import Config, Item, Parser
7
8
 
@@ -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
@@ -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 rich.console import Console
5
6
  from crackerjack.errors import (
@@ -2,6 +2,7 @@ import io
2
2
  import time
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 rich.panel import Panel
@@ -1,4 +1,5 @@
1
1
  from unittest.mock import MagicMock, patch
2
+
2
3
  import pytest
3
4
  from rich.console import Console
4
5
  from crackerjack.errors import ErrorCode, ExecutionError
@@ -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
@@ -1,6 +1,7 @@
1
1
  """Test cases for multiline function definitions in docstring removal."""
2
2
 
3
3
  import ast
4
+
4
5
  from rich.console import Console
5
6
  from crackerjack.crackerjack import CodeCleaner
6
7
 
@@ -2,6 +2,7 @@ import subprocess
2
2
  from pathlib import Path
3
3
  from typing import Any
4
4
  from unittest import mock
5
+
5
6
  from crackerjack.py313 import (
6
7
  CommandResult,
7
8
  CommandRunner,
@@ -1,4 +1,5 @@
1
1
  from pathlib import Path
2
+
2
3
  from crackerjack.py313 import (
3
4
  CommandResult,
4
5
  HookResult,
@@ -1,4 +1,5 @@
1
1
  import time
2
+
2
3
  import pytest
3
4
 
4
5
 
@@ -2,6 +2,7 @@ import io
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
 
File without changes
File without changes