crackerjack 0.21.2__tar.gz → 0.21.4__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 (89) hide show
  1. {crackerjack-0.21.2 → crackerjack-0.21.4}/PKG-INFO +1 -1
  2. crackerjack-0.21.4/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
  3. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/crackerjack.py +84 -37
  4. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/pyproject.toml +1 -1
  5. {crackerjack-0.21.2 → crackerjack-0.21.4}/pyproject.toml +1 -1
  6. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_crackerjack.py +65 -0
  7. crackerjack-0.21.2/crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
  8. {crackerjack-0.21.2 → crackerjack-0.21.4}/LICENSE +0 -0
  9. {crackerjack-0.21.2 → crackerjack-0.21.4}/README.md +0 -0
  10. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.gitignore +0 -0
  11. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.libcst.codemod.yaml +0 -0
  12. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pdm.toml +0 -0
  13. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pre-commit-config-ai.yaml +0 -0
  14. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pre-commit-config.yaml +0 -0
  15. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pytest_cache/.gitignore +0 -0
  16. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pytest_cache/CACHEDIR.TAG +0 -0
  17. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pytest_cache/README.md +0 -0
  18. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pytest_cache/v/cache/nodeids +0 -0
  19. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.pytest_cache/v/cache/stepwise +0 -0
  20. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/.gitignore +0 -0
  21. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  22. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  23. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  24. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  25. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  26. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  27. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.11/18187162184424859798 +0 -0
  28. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.12/16869036553936192448 +0 -0
  29. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.12/1867267426380906393 +0 -0
  30. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.12/4240757255861806333 +0 -0
  31. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.12/4441409093023629623 +0 -0
  32. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.13/1867267426380906393 +0 -0
  33. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.13/4240757255861806333 +0 -0
  34. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  35. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  36. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  37. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  38. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  39. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  40. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  41. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.12.0/5056746222905752453 +0 -0
  42. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  43. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  44. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  45. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  46. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  47. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  48. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  49. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  50. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  51. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  52. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  53. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  54. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  55. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  56. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  57. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  58. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  59. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  60. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  61. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  62. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  63. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  64. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  65. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  66. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  67. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  68. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/.ruff_cache/CACHEDIR.TAG +0 -0
  69. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/__init__.py +0 -0
  70. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/__main__.py +0 -0
  71. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/errors.py +0 -0
  72. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/interactive.py +0 -0
  73. {crackerjack-0.21.2 → crackerjack-0.21.4}/crackerjack/py313.py +0 -0
  74. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/TESTING.md +0 -0
  75. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/__init__.py +0 -0
  76. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/conftest.py +0 -0
  77. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/data/comments_sample.txt +0 -0
  78. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/data/docstrings_sample.txt +0 -0
  79. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/data/expected_comments_sample.txt +0 -0
  80. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/data/init.py +0 -0
  81. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_crackerjack_runner.py +0 -0
  82. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_errors.py +0 -0
  83. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_interactive.py +0 -0
  84. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_interactive_run.py +0 -0
  85. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_main.py +0 -0
  86. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_py313_advanced.py +0 -0
  87. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_py313_features.py +0 -0
  88. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_pytest_features.py +0 -0
  89. {crackerjack-0.21.2 → crackerjack-0.21.4}/tests/test_structured_errors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crackerjack
3
- Version: 0.21.2
3
+ Version: 0.21.4
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>
@@ -633,7 +633,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
633
633
  )
634
634
  if result.returncode == 0:
635
635
  self.console.print("PDM installed: ✅\n")
636
- self.execute_command(["pdm", "lock"])
636
+ self.execute_command(["pdm", "sync"])
637
637
  self.console.print("Lock file updated: ✅\n")
638
638
  else:
639
639
  self.console.print(
@@ -657,19 +657,30 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
657
657
  self.console.print("\nCleaning tests directory...\n")
658
658
  self.code_cleaner.clean_files(tests_dir)
659
659
 
660
- def _prepare_pytest_command(self, options: OptionsProtocol) -> list[str]:
661
- test = ["pytest"]
662
- project_size = self._detect_project_size()
660
+ def _get_test_timeout(self, options: OptionsProtocol, project_size: str) -> int:
663
661
  if options.test_timeout > 0:
664
- test_timeout = options.test_timeout
665
- else:
666
- test_timeout = (
667
- 360
668
- if project_size == "large"
669
- else 240
670
- if project_size == "medium"
671
- else 120
672
- )
662
+ return options.test_timeout
663
+ return (
664
+ 360 if project_size == "large" else 240 if project_size == "medium" else 120
665
+ )
666
+
667
+ def _add_ai_agent_flags(
668
+ self, test: list[str], options: OptionsProtocol, test_timeout: int
669
+ ) -> None:
670
+ test.extend(
671
+ [
672
+ "--junitxml=test-results.xml",
673
+ "--cov-report=json:coverage.json",
674
+ "--tb=short",
675
+ "--no-header",
676
+ "--quiet",
677
+ f"--timeout={test_timeout}",
678
+ ]
679
+ )
680
+ if options.benchmark or options.benchmark_regression:
681
+ test.append("--benchmark-json=benchmark.json")
682
+
683
+ def _add_standard_flags(self, test: list[str], test_timeout: int) -> None:
673
684
  test.extend(
674
685
  [
675
686
  "--capture=fd",
@@ -680,17 +691,22 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
680
691
  f"--timeout={test_timeout}",
681
692
  ]
682
693
  )
683
- if options.benchmark or options.benchmark_regression:
684
- if options.benchmark:
685
- test.extend(["--benchmark", "--benchmark-autosave"])
686
- if options.benchmark_regression:
687
- test.extend(
688
- [
689
- "--benchmark-regression",
690
- f"--benchmark-regression-threshold={options.benchmark_regression_threshold}",
691
- ]
692
- )
693
- elif options.test_workers > 0:
694
+
695
+ def _add_benchmark_flags(self, test: list[str], options: OptionsProtocol) -> None:
696
+ if options.benchmark:
697
+ test.extend(["--benchmark", "--benchmark-autosave"])
698
+ if options.benchmark_regression:
699
+ test.extend(
700
+ [
701
+ "--benchmark-regression",
702
+ f"--benchmark-regression-threshold={options.benchmark_regression_threshold}",
703
+ ]
704
+ )
705
+
706
+ def _add_worker_flags(
707
+ self, test: list[str], options: OptionsProtocol, project_size: str
708
+ ) -> None:
709
+ if options.test_workers > 0:
694
710
  if options.test_workers == 1:
695
711
  test.append("-vs")
696
712
  else:
@@ -701,6 +717,20 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
701
717
  test.extend(["-xvs", "-n", "auto"])
702
718
  else:
703
719
  test.append("-xvs")
720
+
721
+ def _prepare_pytest_command(self, options: OptionsProtocol) -> list[str]:
722
+ test = ["pytest"]
723
+ project_size = self._detect_project_size()
724
+ test_timeout = self._get_test_timeout(options, project_size)
725
+ if getattr(options, "ai_agent", False):
726
+ self._add_ai_agent_flags(test, options, test_timeout)
727
+ else:
728
+ self._add_standard_flags(test, test_timeout)
729
+ if options.benchmark or options.benchmark_regression:
730
+ self._add_benchmark_flags(test, options)
731
+ else:
732
+ self._add_worker_flags(test, options, project_size)
733
+
704
734
  return test
705
735
 
706
736
  def _detect_project_size(self) -> str:
@@ -717,22 +747,39 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
717
747
  return "medium"
718
748
  else:
719
749
  return "small"
720
- except Exception:
750
+ except (OSError, PermissionError):
721
751
  return "medium"
722
752
 
753
+ def _print_ai_agent_files(self, options: t.Any) -> None:
754
+ if getattr(options, "ai_agent", False):
755
+ self.console.print("📄 Structured test results: test-results.xml")
756
+ self.console.print("📊 Coverage report: coverage.json")
757
+ if options.benchmark or options.benchmark_regression:
758
+ self.console.print("⏱️ Benchmark results: benchmark.json")
759
+
760
+ def _handle_test_failure(self, result: t.Any, options: t.Any) -> None:
761
+ if result.stderr:
762
+ self.console.print(result.stderr)
763
+ self.console.print("\n\n❌ Tests failed. Please fix errors.\n")
764
+ self._print_ai_agent_files(options)
765
+ raise SystemExit(1)
766
+
767
+ def _handle_test_success(self, options: t.Any) -> None:
768
+ self.console.print("\n\n✅ Tests passed successfully!\n")
769
+ self._print_ai_agent_files(options)
770
+
723
771
  def _run_tests(self, options: t.Any) -> None:
724
- if options.test:
725
- self.console.print("\n\nRunning tests...\n")
726
- test_command = self._prepare_pytest_command(options)
727
- result = self.execute_command(test_command, capture_output=True, text=True)
728
- if result.stdout:
729
- self.console.print(result.stdout)
730
- if result.returncode > 0:
731
- if result.stderr:
732
- self.console.print(result.stderr)
733
- self.console.print("\n\n❌ Tests failed. Please fix errors.\n")
734
- raise SystemExit(1)
735
- self.console.print("\n\n✅ Tests passed successfully!\n")
772
+ if not options.test:
773
+ return
774
+ self.console.print("\n\nRunning tests...\n")
775
+ test_command = self._prepare_pytest_command(options)
776
+ result = self.execute_command(test_command, capture_output=True, text=True)
777
+ if result.stdout:
778
+ self.console.print(result.stdout)
779
+ if result.returncode > 0:
780
+ self._handle_test_failure(result, options)
781
+ else:
782
+ self._handle_test_success(options)
736
783
 
737
784
  def _bump_version(self, options: OptionsProtocol) -> None:
738
785
  for option in (options.publish, options.bump):
@@ -4,7 +4,7 @@ requires = [ "pdm-backend" ]
4
4
 
5
5
  [project]
6
6
  name = "crackerjack"
7
- version = "0.21.1"
7
+ version = "0.21.3"
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.2"
9
+ version = "0.21.4"
10
10
  description = "Crackerjack: code quality toolkit"
11
11
  readme = "README.md"
12
12
  keywords = [
@@ -392,6 +392,71 @@ class TestCrackerjackProcess:
392
392
  mock_confirm.assert_not_called()
393
393
  mock_exec.assert_called_once_with(["pdm", "bump", "micro"])
394
394
 
395
+ def test_prepare_pytest_command_ai_agent_mode(
396
+ self,
397
+ mock_execute: MagicMock,
398
+ mock_console_print: MagicMock,
399
+ tmp_path: Path,
400
+ tmp_path_package: Path,
401
+ create_package_dir: None,
402
+ options_factory: t.Callable[..., OptionsForTesting],
403
+ ) -> None:
404
+ options = options_factory(test=True, ai_agent=True, no_config_updates=True)
405
+ pytest_command = (_cj := Crackerjack(dry_run=True))._prepare_pytest_command(
406
+ options
407
+ )
408
+
409
+ assert "--junitxml=test-results.xml" in pytest_command
410
+ assert "--cov-report=json:coverage.json" in pytest_command
411
+ assert "--quiet" in pytest_command
412
+ assert "--tb=short" in pytest_command
413
+ assert "--no-header" in pytest_command
414
+
415
+ def test_prepare_pytest_command_ai_agent_with_benchmark(
416
+ self,
417
+ mock_execute: MagicMock,
418
+ mock_console_print: MagicMock,
419
+ tmp_path: Path,
420
+ tmp_path_package: Path,
421
+ create_package_dir: None,
422
+ options_factory: t.Callable[..., OptionsForTesting],
423
+ ) -> None:
424
+ options = options_factory(
425
+ test=True, ai_agent=True, benchmark=True, no_config_updates=True
426
+ )
427
+ pytest_command = (_cj := Crackerjack(dry_run=True))._prepare_pytest_command(
428
+ options
429
+ )
430
+
431
+ assert "--junitxml=test-results.xml" in pytest_command
432
+ assert "--cov-report=json:coverage.json" in pytest_command
433
+ assert "--benchmark-json=benchmark.json" in pytest_command
434
+ assert "--benchmark" in pytest_command
435
+ assert "--benchmark-autosave" in pytest_command
436
+
437
+ def test_prepare_pytest_command_normal_mode(
438
+ self,
439
+ mock_execute: MagicMock,
440
+ mock_console_print: MagicMock,
441
+ tmp_path: Path,
442
+ tmp_path_package: Path,
443
+ create_package_dir: None,
444
+ options_factory: t.Callable[..., OptionsForTesting],
445
+ ) -> None:
446
+ options = options_factory(test=True, ai_agent=False, no_config_updates=True)
447
+ pytest_command = (_cj := Crackerjack(dry_run=True))._prepare_pytest_command(
448
+ options
449
+ )
450
+
451
+ assert "--junitxml=test-results.xml" not in pytest_command
452
+ assert "--cov-report=json:coverage.json" not in pytest_command
453
+ assert "--benchmark-json=benchmark.json" not in pytest_command
454
+ assert "--quiet" not in pytest_command
455
+
456
+ assert "--capture=fd" in pytest_command
457
+ assert "--disable-warnings" in pytest_command
458
+ assert "--durations=0" in pytest_command
459
+
395
460
  def test_process_with_publish_option(
396
461
  self,
397
462
  mock_execute: MagicMock,
File without changes
File without changes