crackerjack 0.22.8__py3-none-any.whl → 0.24.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (67) hide show
  1. crackerjack/.pre-commit-config-ai.yaml +2 -11
  2. crackerjack/.pre-commit-config.yaml +2 -9
  3. crackerjack/crackerjack.py +66 -26
  4. crackerjack/pyproject.toml +5 -7
  5. {crackerjack-0.22.8.dist-info → crackerjack-0.24.0.dist-info}/METADATA +24 -25
  6. crackerjack-0.24.0.dist-info/RECORD +16 -0
  7. {crackerjack-0.22.8.dist-info → crackerjack-0.24.0.dist-info}/WHEEL +1 -1
  8. crackerjack/.pytest_cache/.gitignore +0 -2
  9. crackerjack/.pytest_cache/CACHEDIR.TAG +0 -4
  10. crackerjack/.pytest_cache/README.md +0 -8
  11. crackerjack/.pytest_cache/v/cache/nodeids +0 -1
  12. crackerjack/.pytest_cache/v/cache/stepwise +0 -1
  13. crackerjack/.ruff_cache/.gitignore +0 -1
  14. crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  15. crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  16. crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  17. crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  18. crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  19. crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  20. crackerjack/.ruff_cache/0.11.11/18187162184424859798 +0 -0
  21. crackerjack/.ruff_cache/0.11.12/16869036553936192448 +0 -0
  22. crackerjack/.ruff_cache/0.11.12/1867267426380906393 +0 -0
  23. crackerjack/.ruff_cache/0.11.12/4240757255861806333 +0 -0
  24. crackerjack/.ruff_cache/0.11.12/4441409093023629623 +0 -0
  25. crackerjack/.ruff_cache/0.11.13/1867267426380906393 +0 -0
  26. crackerjack/.ruff_cache/0.11.13/4240757255861806333 +0 -0
  27. crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  28. crackerjack/.ruff_cache/0.11.3/9818742842212983150 +0 -0
  29. crackerjack/.ruff_cache/0.11.4/9818742842212983150 +0 -0
  30. crackerjack/.ruff_cache/0.11.6/3557596832929915217 +0 -0
  31. crackerjack/.ruff_cache/0.11.7/10386934055395314831 +0 -0
  32. crackerjack/.ruff_cache/0.11.7/3557596832929915217 +0 -0
  33. crackerjack/.ruff_cache/0.11.8/530407680854991027 +0 -0
  34. crackerjack/.ruff_cache/0.12.0/5056746222905752453 +0 -0
  35. crackerjack/.ruff_cache/0.12.1/5056746222905752453 +0 -0
  36. crackerjack/.ruff_cache/0.12.2/5056746222905752453 +0 -0
  37. crackerjack/.ruff_cache/0.12.3/5056746222905752453 +0 -0
  38. crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  39. crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  40. crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  41. crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  42. crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  43. crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  44. crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  45. crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  46. crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  47. crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  48. crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  49. crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  50. crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  51. crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  52. crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  53. crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  54. crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  55. crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  56. crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  57. crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  58. crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  59. crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  60. crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  61. crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  62. crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  63. crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  64. crackerjack/.ruff_cache/CACHEDIR.TAG +0 -1
  65. crackerjack-0.22.8.dist-info/RECORD +0 -74
  66. crackerjack-0.22.8.dist-info/entry_points.txt +0 -4
  67. {crackerjack-0.22.8.dist-info → crackerjack-0.24.0.dist-info}/licenses/LICENSE +0 -0
@@ -29,19 +29,10 @@ repos:
29
29
  rev: "v2.6.0"
30
30
  hooks:
31
31
  - id: pyproject-fmt
32
+ args: ["-n"]
32
33
  verbose: true
33
34
 
34
35
  # Package management - once structure is valid
35
- - repo: https://github.com/pdm-project/pdm
36
- rev: 2.25.3
37
- hooks:
38
- - id: pdm-lock-check
39
- verbose: true
40
- - id: pdm-sync
41
- verbose: true
42
- additional_dependencies:
43
- - keyring
44
-
45
36
  - repo: https://github.com/astral-sh/uv-pre-commit
46
37
  rev: 0.7.15
47
38
  hooks:
@@ -54,7 +45,7 @@ repos:
54
45
  rev: v1.5.0
55
46
  hooks:
56
47
  - id: detect-secrets
57
- exclude: 'pdm\.lock|uv\.lock|pyproject\.toml|tests/.*|docs/.*|.*\.md'
48
+ exclude: 'uv\.lock|pyproject\.toml|tests/.*|docs/.*|.*\.md'
58
49
  verbose: true
59
50
 
60
51
  # Code quality tier 1 - quick fixes
@@ -18,16 +18,9 @@ repos:
18
18
  rev: "v2.6.0"
19
19
  hooks:
20
20
  - id: pyproject-fmt
21
+ args: ["-n"]
21
22
 
22
23
  # Package management - once structure is valid
23
- - repo: https://github.com/pdm-project/pdm
24
- rev: 2.25.4
25
- hooks:
26
- - id: pdm-lock-check
27
- - id: pdm-sync
28
- additional_dependencies:
29
- - keyring
30
-
31
24
  - repo: https://github.com/astral-sh/uv-pre-commit
32
25
  rev: 0.7.20
33
26
  hooks:
@@ -39,7 +32,7 @@ repos:
39
32
  rev: v1.5.0
40
33
  hooks:
41
34
  - id: detect-secrets
42
- exclude: 'pdm\.lock|uv\.lock|pyproject\.toml|tests/.*|docs/.*|.*\.md'
35
+ exclude: 'uv\.lock|pyproject\.toml|tests/.*|docs/.*|.*\.md'
43
36
 
44
37
  # Code quality tier 1 - quick fixes
45
38
  - repo: https://github.com/codespell-project/codespell
@@ -1,7 +1,9 @@
1
1
  import re
2
2
  import subprocess
3
3
  import typing as t
4
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
5
  from contextlib import suppress
6
+ from functools import lru_cache
5
7
  from pathlib import Path
6
8
  from subprocess import CompletedProcess
7
9
  from subprocess import run as execute
@@ -56,9 +58,30 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
56
58
  def clean_files(self, pkg_dir: Path | None) -> None:
57
59
  if pkg_dir is None:
58
60
  return
59
- for file_path in pkg_dir.rglob("*.py"):
60
- if not str(file_path.parent).startswith("__"):
61
- self.clean_file(file_path)
61
+ python_files = [
62
+ file_path
63
+ for file_path in pkg_dir.rglob("*.py")
64
+ if not str(file_path.parent).startswith("__")
65
+ ]
66
+ if not python_files:
67
+ return
68
+ max_workers = min(len(python_files), 4)
69
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
70
+ future_to_file = {
71
+ executor.submit(self.clean_file, file_path): file_path
72
+ for file_path in python_files
73
+ }
74
+ for future in as_completed(future_to_file):
75
+ file_path = future_to_file[future]
76
+ try:
77
+ future.result()
78
+ except Exception as e:
79
+ self.console.print(
80
+ f"[bold bright_red]❌ Error cleaning {file_path}: {e}[/bold bright_red]"
81
+ )
82
+ self._cleanup_cache_directories(pkg_dir)
83
+
84
+ def _cleanup_cache_directories(self, pkg_dir: Path) -> None:
62
85
  with suppress(PermissionError, OSError):
63
86
  pycache_dir = pkg_dir / "__pycache__"
64
87
  if pycache_dir.exists():
@@ -423,14 +446,9 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
423
446
  import_tracker["in_imports"] = False
424
447
  import_tracker["last_import_type"] = None
425
448
 
426
- def _is_stdlib_import(self, stripped_line: str) -> bool:
427
- try:
428
- if stripped_line.startswith("from "):
429
- module = stripped_line.split()[1].split(".")[0]
430
- else:
431
- module = stripped_line.split()[1].split(".")[0]
432
- except IndexError:
433
- return False
449
+ @staticmethod
450
+ @lru_cache(maxsize=256)
451
+ def _is_stdlib_module(module: str) -> bool:
434
452
  stdlib_modules = {
435
453
  "os",
436
454
  "sys",
@@ -511,6 +529,16 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
511
529
  }
512
530
  return module in stdlib_modules
513
531
 
532
+ def _is_stdlib_import(self, stripped_line: str) -> bool:
533
+ try:
534
+ if stripped_line.startswith("from "):
535
+ module = stripped_line.split()[1].split(".")[0]
536
+ else:
537
+ module = stripped_line.split()[1].split(".")[0]
538
+ except IndexError:
539
+ return False
540
+ return CodeCleaner._is_stdlib_module(module)
541
+
514
542
  def _is_local_import(self, stripped_line: str) -> bool:
515
543
  return stripped_line.startswith("from .") or " . " in stripped_line
516
544
 
@@ -805,6 +833,7 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
805
833
  self.pkg_toml_path.write_text(dumps(pkg_toml_config))
806
834
 
807
835
  def copy_configs(self) -> None:
836
+ configs_to_add = []
808
837
  for config in config_files:
809
838
  config_path = self.our_path / config
810
839
  pkg_config_path = self.pkg_path / config
@@ -816,7 +845,9 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
816
845
  pkg_config_path.write_text(
817
846
  config_path.read_text().replace("crackerjack", self.pkg_name)
818
847
  )
819
- self.execute_command(["git", "add", config])
848
+ configs_to_add.append(config)
849
+ if configs_to_add:
850
+ self.execute_command(["git", "add"] + configs_to_add)
820
851
 
821
852
  def execute_command(
822
853
  self, cmd: list[str], **kwargs: t.Any
@@ -843,7 +874,7 @@ class ProjectManager(BaseModel, arbitrary_types_allowed=True):
843
874
  def update_pkg_configs(self) -> None:
844
875
  self.config_manager.copy_configs()
845
876
  installed_pkgs = self.execute_command(
846
- ["pdm", "list", "--freeze"], capture_output=True, text=True
877
+ ["uv", "pip", "list", "--freeze"], capture_output=True, text=True
847
878
  ).stdout.splitlines()
848
879
  if not len([pkg for pkg in installed_pkgs if "pre-commit" in pkg]):
849
880
  self.console.print("\n" + "─" * 60)
@@ -851,17 +882,15 @@ class ProjectManager(BaseModel, arbitrary_types_allowed=True):
851
882
  "[bold bright_blue]⚡ INIT[/bold bright_blue] [bold bright_white]First-time project setup[/bold bright_white]"
852
883
  )
853
884
  self.console.print("─" * 60 + "\n")
854
- self.execute_command(["pdm", "self", "add", "keyring"])
855
- self.execute_command(["pdm", "config", "python.use_uv", "true"])
885
+ self.execute_command(["uv", "tool", "install", "keyring"])
856
886
  self.execute_command(["git", "init"])
857
887
  self.execute_command(["git", "branch", "-m", "main"])
858
- self.execute_command(["git", "add", "pyproject.toml"])
859
- self.execute_command(["git", "add", "pdm.lock"])
888
+ self.execute_command(["git", "add", "pyproject.toml", "pdm.lock"])
889
+ self.execute_command(["git", "config", "advice.addIgnoredFile", "false"])
860
890
  install_cmd = ["pre-commit", "install"]
861
891
  if hasattr(self, "options") and getattr(self.options, "ai_agent", False):
862
892
  install_cmd.extend(["-c", ".pre-commit-config-ai.yaml"])
863
893
  self.execute_command(install_cmd)
864
- self.execute_command(["git", "config", "advice.addIgnoredFile", "false"])
865
894
  self.config_manager.update_pyproject_configs()
866
895
 
867
896
  def run_pre_commit(self) -> None:
@@ -875,7 +904,7 @@ class ProjectManager(BaseModel, arbitrary_types_allowed=True):
875
904
  cmd.extend(["-c", ".pre-commit-config-ai.yaml"])
876
905
  check_all = self.execute_command(cmd)
877
906
  if check_all.returncode > 0:
878
- self.execute_command(["pdm", "lock"])
907
+ self.execute_command(["uv", "lock"])
879
908
  self.console.print("\n[bold green]✓ Dependencies locked[/bold green]\n")
880
909
  check_all = self.execute_command(cmd)
881
910
  if check_all.returncode > 0:
@@ -906,9 +935,11 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
906
935
  code_cleaner: CodeCleaner | None = None
907
936
  config_manager: ConfigManager | None = None
908
937
  project_manager: ProjectManager | None = None
938
+ _file_cache: dict[str, list[Path]] = {}
909
939
 
910
940
  def __init__(self, **data: t.Any) -> None:
911
941
  super().__init__(**data)
942
+ self._file_cache = {}
912
943
  self.code_cleaner = CodeCleaner(console=self.console)
913
944
  self.config_manager = ConfigManager(
914
945
  our_path=self.our_path,
@@ -946,7 +977,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
946
977
  if not options.no_config_updates:
947
978
  self.project_manager.update_pkg_configs()
948
979
  result: CompletedProcess[str] = self.execute_command(
949
- ["pdm", "install"], capture_output=True, text=True
980
+ ["uv", "sync"], capture_output=True, text=True
950
981
  )
951
982
  if result.returncode == 0:
952
983
  self.console.print(
@@ -954,7 +985,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
954
985
  )
955
986
  else:
956
987
  self.console.print(
957
- "\n\n[bold red]❌ PDM installation failed. Is PDM installed? Run `pipx install pdm` and try again.[/bold red]\n\n"
988
+ "\n\n[bold red]❌ UV sync failed. Is UV installed? Run `pipx install uv` and try again.[/bold red]\n\n"
958
989
  )
959
990
 
960
991
  def _update_precommit(self, options: t.Any) -> None:
@@ -1058,12 +1089,21 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
1058
1089
  self._add_worker_flags(test, options, project_size)
1059
1090
  return test
1060
1091
 
1092
+ def _get_cached_files(self, pattern: str) -> list[Path]:
1093
+ cache_key = f"{self.pkg_path}:{pattern}"
1094
+ if cache_key not in self._file_cache:
1095
+ try:
1096
+ self._file_cache[cache_key] = list(self.pkg_path.rglob(pattern))
1097
+ except (OSError, PermissionError):
1098
+ self._file_cache[cache_key] = []
1099
+ return self._file_cache[cache_key]
1100
+
1061
1101
  def _detect_project_size(self) -> str:
1062
1102
  if self.pkg_name in ("acb", "fastblocks"):
1063
1103
  return "large"
1064
1104
  try:
1065
- py_files = list(self.pkg_path.rglob("*.py"))
1066
- test_files = list(self.pkg_path.rglob("test_*.py"))
1105
+ py_files = self._get_cached_files("*.py")
1106
+ test_files = self._get_cached_files("test_*.py")
1067
1107
  total_files = len(py_files)
1068
1108
  num_test_files = len(test_files)
1069
1109
  if total_files > 100 or num_test_files > 50:
@@ -1139,7 +1179,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
1139
1179
  f"[bold yellow]⏭️ Skipping {option} version bump[/bold yellow]"
1140
1180
  )
1141
1181
  return
1142
- self.execute_command(["pdm", "bump", option])
1182
+ self.execute_command(["uv", "version", "--bump", option])
1143
1183
  break
1144
1184
 
1145
1185
  def _publish_project(self, options: OptionsProtocol) -> None:
@@ -1150,7 +1190,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
1150
1190
  )
1151
1191
  self.console.print("-" * 60 + "\n")
1152
1192
  build = self.execute_command(
1153
- ["pdm", "build"], capture_output=True, text=True
1193
+ ["uv", "build"], capture_output=True, text=True
1154
1194
  )
1155
1195
  self.console.print(build.stdout)
1156
1196
  if build.returncode > 0:
@@ -1159,7 +1199,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
1159
1199
  "[bold bright_red]❌ Build failed. Please fix errors.[/bold bright_red]"
1160
1200
  )
1161
1201
  raise SystemExit(1)
1162
- self.execute_command(["pdm", "publish", "--no-build"])
1202
+ self.execute_command(["uv", "publish"])
1163
1203
 
1164
1204
  def _commit_and_push(self, options: OptionsProtocol) -> None:
1165
1205
  if options.commit:
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- build-backend = "pdm.backend"
3
- requires = [ "pdm-backend" ]
2
+ build-backend = "hatchling.build"
3
+ requires = [ "hatchling" ]
4
4
 
5
5
  [project]
6
6
  name = "crackerjack"
7
- version = "0.22.7"
7
+ version = "0.22.8"
8
8
  description = "Crackerjack: code quality toolkit"
9
9
  readme = "README.md"
10
10
  keywords = [
@@ -42,9 +42,8 @@ classifiers = [
42
42
  ]
43
43
  dependencies = [
44
44
  "autotyping>=24.9",
45
+ "hatchling>=1.25",
45
46
  "keyring>=25.6",
46
- "pdm>=2.25.4",
47
- "pdm-bump>=0.9.12",
48
47
  "pre-commit>=4.2",
49
48
  "pydantic>=2.11.7",
50
49
  "pytest>=8.4.1",
@@ -205,8 +204,8 @@ paths = [
205
204
  ]
206
205
  deps-file = "pyproject.toml"
207
206
  exclude-deps = [
208
- "pdm-bump",
209
207
  "autotyping",
208
+ "hatchling",
210
209
  "pre-commit",
211
210
  "pytest",
212
211
  "pytest-asyncio",
@@ -214,7 +213,6 @@ exclude-deps = [
214
213
  "pytest-mock",
215
214
  "pytest-xdist",
216
215
  "pytest-benchmark",
217
- "pdm",
218
216
  "pyfiglet",
219
217
  "pyyaml",
220
218
  "uv",
@@ -1,11 +1,15 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: crackerjack
3
- Version: 0.22.8
3
+ Version: 0.24.0
4
4
  Summary: Crackerjack: code quality toolkit
5
- Keywords: bandit,black,creosote,mypy,pyright,pytest,refurb,ruff
6
- Author-Email: lesleslie <les@wedgwoodwebworks.com>
7
- Maintainer-Email: lesleslie <les@wedgwoodwebworks.com>
5
+ Project-URL: documentation, https://github.com/lesleslie/crackerjack
6
+ Project-URL: homepage, https://github.com/lesleslie/crackerjack
7
+ Project-URL: repository, https://github.com/lesleslie/crackerjack
8
+ Author-email: lesleslie <les@wedgwoodwebworks.com>
9
+ Maintainer-email: lesleslie <les@wedgwoodwebworks.com>
8
10
  License: BSD-3-CLAUSE
11
+ License-File: LICENSE
12
+ Keywords: bandit,black,creosote,mypy,pyright,pytest,refurb,ruff
9
13
  Classifier: Development Status :: 4 - Beta
10
14
  Classifier: Environment :: Console
11
15
  Classifier: License :: OSI Approved :: BSD License
@@ -18,23 +22,19 @@ Classifier: Topic :: Software Development :: Quality Assurance
18
22
  Classifier: Topic :: Software Development :: Testing
19
23
  Classifier: Topic :: Utilities
20
24
  Classifier: Typing :: Typed
21
- Project-URL: documentation, https://github.com/lesleslie/crackerjack
22
- Project-URL: homepage, https://github.com/lesleslie/crackerjack
23
- Project-URL: repository, https://github.com/lesleslie/crackerjack
24
25
  Requires-Python: >=3.13
25
26
  Requires-Dist: autotyping>=24.9
27
+ Requires-Dist: hatchling>=1.25
26
28
  Requires-Dist: keyring>=25.6
27
- Requires-Dist: pdm>=2.25.4
28
- Requires-Dist: pdm-bump>=0.9.12
29
29
  Requires-Dist: pre-commit>=4.2
30
30
  Requires-Dist: pydantic>=2.11.7
31
- Requires-Dist: pytest>=8.4.1
32
31
  Requires-Dist: pytest-asyncio>=1
33
32
  Requires-Dist: pytest-benchmark>=5.1
34
33
  Requires-Dist: pytest-cov>=6.2.1
35
34
  Requires-Dist: pytest-mock>=3.14.1
36
35
  Requires-Dist: pytest-timeout>=2.4
37
36
  Requires-Dist: pytest-xdist>=3.8
37
+ Requires-Dist: pytest>=8.4.1
38
38
  Requires-Dist: pyyaml>=6.0.2
39
39
  Requires-Dist: rich>=14
40
40
  Requires-Dist: tomli-w>=1.2
@@ -49,7 +49,6 @@ Description-Content-Type: text/markdown
49
49
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
50
50
  [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
51
51
  [![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
52
- [![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev)
53
52
  [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
54
53
  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
55
54
 
@@ -75,7 +74,7 @@ Crackerjack solves three critical challenges in Python development:
75
74
  - **Challenge**: Publishing Python packages involves many manual, error-prone steps
76
75
  - **Solution**: Crackerjack automates the entire release process from testing to version bumping to publishing
77
76
 
78
- Crackerjack integrates powerful tools like Ruff, PDM, pre-commit, pytest, and more into a cohesive system that ensures code quality, consistency, and reliability. It's designed for developers who value both productivity and excellence.
77
+ Crackerjack integrates powerful tools like Ruff, UV, pre-commit, pytest, and more into a cohesive system that ensures code quality, consistency, and reliability. It's designed for developers who value both productivity and excellence.
79
78
 
80
79
  ---
81
80
 
@@ -85,9 +84,9 @@ Crackerjack integrates powerful tools like Ruff, PDM, pre-commit, pytest, and mo
85
84
 
86
85
  If you're new to Crackerjack, follow these steps:
87
86
  1. **Install Python 3.13:** Ensure you have Python 3.13 or higher installed.
88
- 2. **Install PDM:**
87
+ 2. **Install UV:**
89
88
  ```
90
- pipx install pdm
89
+ pipx install uv
91
90
  ```
92
91
  3. **Install Crackerjack:**
93
92
  ```
@@ -122,7 +121,7 @@ Crackerjack is built on the following core principles:
122
121
 
123
122
  ### Project Management
124
123
  - **Effortless Project Setup:** Initializes new Python projects with a standard directory structure, `pyproject.toml`, and essential configuration files
125
- - **PDM Integration:** Manages dependencies and virtual environments using [PDM](https://pdm.fming.dev/) with [uv](https://github.com/astral-sh/uv) for lightning-fast package operations
124
+ - **UV Integration:** Manages dependencies and virtual environments using [UV](https://github.com/astral-sh/uv) for lightning-fast package operations
126
125
  - **Dependency Management:** Automatically detects and manages project dependencies
127
126
 
128
127
  ### Code Quality
@@ -135,7 +134,7 @@ Crackerjack is built on the following core principles:
135
134
  ### Testing & Deployment
136
135
  - **Built-in Testing:** Automatically runs tests using `pytest`
137
136
  - **Easy Version Bumping:** Provides commands to bump the project version (micro, minor, or major)
138
- - **Simplified Publishing:** Automates publishing to PyPI via PDM
137
+ - **Simplified Publishing:** Automates publishing to PyPI via UV
139
138
 
140
139
  ### Git Integration
141
140
  - **Commit and Push:** Commits and pushes your changes with standardized commit messages
@@ -155,7 +154,7 @@ Crackerjack is built on the following core principles:
155
154
 
156
155
  Crackerjack automatically installs and manages these pre-commit hooks:
157
156
 
158
- 1. **pdm-lock-check:** Ensures the `pdm.lock` file is up to date.
157
+ 1. **uv-lock:** Ensures the `uv.lock` file is up to date.
159
158
  2. **Core pre-commit-hooks:** Essential hooks from [pre-commit-hooks](https://github.com/pre-commit/pre-commit-hooks) (e.g., `trailing-whitespace`, `end-of-file-fixer`).
160
159
  3. **Ruff:** [Ruff](https://github.com/astral-sh/ruff) for linting, code formatting, and general code style enforcement.
161
160
  4. **Vulture:** [Vulture](https://github.com/jendrikseipp/vulture) to identify dead code.
@@ -181,7 +180,7 @@ Crackerjack projects adhere to these guidelines:
181
180
  - **Protocol-Based Design:** Use `t.Protocol` for interface definitions instead of abstract base classes.
182
181
  - **Constants and Config:** Do not use all-caps for constants or configuration settings.
183
182
  - **Path Parameters:** Functions that handle file operations should accept `pathlib.Path` objects as parameters.
184
- - **Dependency Management:** Use PDM for dependency management, package building, and publishing.
183
+ - **Dependency Management:** Use UV for dependency management, package building, and publishing.
185
184
  - **Testing:** Use pytest as your testing framework.
186
185
  - **Python Version:** Crackerjack projects target Python 3.13+ and use the latest language features.
187
186
  - **Clear Code:** Avoid overly complex code.
@@ -254,10 +253,10 @@ python -m crackerjack -t --benchmark-regression --benchmark-regression-threshold
254
253
  ## Installation
255
254
 
256
255
  1. **Python:** Ensure you have Python 3.13 or higher installed.
257
- 2. **PDM:** Install [PDM](https://pdm.fming.dev/) using `pipx`:
256
+ 2. **UV:** Install [UV](https://github.com/astral-sh/uv) using `pipx`:
258
257
 
259
258
  ```
260
- pipx install pdm
259
+ pipx install uv
261
260
  ```
262
261
 
263
262
  3. **Crackerjack:** Install Crackerjack and initialize in your project root using:
@@ -347,7 +346,7 @@ runner.process(MyOptions())
347
346
  - `-n`, `--no-config-updates`: Skip updating configuration files (e.g., `pyproject.toml`).
348
347
  - `-u`, `--update-precommit`: Update pre-commit hooks to the latest versions.
349
348
  - `-v`, `--verbose`: Enable verbose output.
350
- - `-p`, `--publish <micro|minor|major>`: Bump the project version and publish to PyPI using PDM.
349
+ - `-p`, `--publish <micro|minor|major>`: Bump the project version and publish to PyPI using UV.
351
350
  - `-b`, `--bump <micro|minor|major>`: Bump the project version without publishing.
352
351
  - `-r`, `--pr`: Create a pull request to the upstream repository.
353
352
  - `-s`, `--skip-hooks`: Skip running pre-commit hooks (useful with `-t`).
@@ -569,7 +568,7 @@ To contribute:
569
568
 
570
569
  1. Add Crackerjack as a development dependency to your project:
571
570
  ```
572
- pdm add -G dev crackerjack
571
+ uv add --dev crackerjack
573
572
  ```
574
573
 
575
574
  2. Run checks and tests before submitting:
@@ -596,11 +595,11 @@ Crackerjack is designed with modern Python principles in mind:
596
595
 
597
596
  ## Acknowledgments
598
597
 
599
- - **PDM:** For excellent dependency and virtual environment management.
598
+ - **UV:** For excellent dependency and virtual environment management.
600
599
  - **Ruff:** For lightning-fast linting and code formatting.
601
600
  - **pre-commit:** For the robust hook management system.
602
601
  - **pytest:** For the flexible and powerful testing framework.
603
- - **uv:** For greatly improving PDM speeds.
602
+ - **PDM:** For the original inspiration for dependency management patterns.
604
603
  - **bandit:** For finding security vulnerabilities.
605
604
  - **vulture:** For dead code detection.
606
605
  - **creosote:** For unused dependency detection.
@@ -0,0 +1,16 @@
1
+ crackerjack/.gitignore,sha256=n8cD6U16L3XZn__PvhYm_F7-YeFHFucHCyxWj2NZCGs,259
2
+ crackerjack/.libcst.codemod.yaml,sha256=a8DlErRAIPV1nE6QlyXPAzTOgkB24_spl2E9hphuf5s,772
3
+ crackerjack/.pdm.toml,sha256=dZe44HRcuxxCFESGG8SZIjmc-cGzSoyK3Hs6t4NYA8w,23
4
+ crackerjack/.pre-commit-config-ai.yaml,sha256=kPAU41yuX8XU00HDl6Y2mX-L3aLMYTNo8fnFWEZE4mM,3112
5
+ crackerjack/.pre-commit-config.yaml,sha256=KwzEBj84K5Vp09aYXlk2H7LFlMJl6jToOl8q4u3IxuU,2480
6
+ crackerjack/__init__.py,sha256=8tBSPAru_YDuPpjz05cL7pNbZjYFoRT_agGd_FWa3gY,839
7
+ crackerjack/__main__.py,sha256=lEyi83ChuehqEJgUQ6Ib4ByOofvmhi_0M7oFamMC_1I,6407
8
+ crackerjack/crackerjack.py,sha256=PC_D6GBz7ImVuTR3T1QSTg_ocG7qrEBnRn91xD_It18,49399
9
+ crackerjack/errors.py,sha256=Wcv0rXfzV9pHOoXYrhQEjyJd4kUUBbdiY-5M9nI8pDw,4050
10
+ crackerjack/interactive.py,sha256=pFItgRUyjOakABLCRz6nIp6_Ycx2LBSeojpYNiTelv0,16126
11
+ crackerjack/py313.py,sha256=buYE7LO11Q64ffowEhTZRFQoAGj_8sg3DTlZuv8M9eo,5890
12
+ crackerjack/pyproject.toml,sha256=0DP3infyN5sFOe6KSS18KU2MKJHvYhh6djjy4zvXfIU,4964
13
+ crackerjack-0.24.0.dist-info/METADATA,sha256=dP0-exESourU6SnO-wLQdkAAGbc7EE4Bqv_-tLF7GG0,26137
14
+ crackerjack-0.24.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ crackerjack-0.24.0.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
16
+ crackerjack-0.24.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.4.5)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,2 +0,0 @@
1
- # Created by pytest automatically.
2
- *
@@ -1,4 +0,0 @@
1
- Signature: 8a477f597d28d172789f06886806bc55
2
- # This file is a cache directory tag created by pytest.
3
- # For information about cache directory tags, see:
4
- # https://bford.info/cachedir/spec.html
@@ -1,8 +0,0 @@
1
- # pytest cache directory #
2
-
3
- This directory contains data from the pytest's cache plugin,
4
- which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
5
-
6
- **Do not** commit this to version control.
7
-
8
- See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- *
@@ -1 +0,0 @@
1
- Signature: 8a477f597d28d172789f06886806bc55
@@ -1,74 +0,0 @@
1
- crackerjack-0.22.8.dist-info/METADATA,sha256=XurKfkh5Zzt8a4aCCE5kuOPF4m8aSdgyLyGZArX6nw0,26251
2
- crackerjack-0.22.8.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- crackerjack-0.22.8.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
- crackerjack-0.22.8.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
5
- crackerjack/.gitignore,sha256=n8cD6U16L3XZn__PvhYm_F7-YeFHFucHCyxWj2NZCGs,259
6
- crackerjack/.libcst.codemod.yaml,sha256=a8DlErRAIPV1nE6QlyXPAzTOgkB24_spl2E9hphuf5s,772
7
- crackerjack/.pdm.toml,sha256=dZe44HRcuxxCFESGG8SZIjmc-cGzSoyK3Hs6t4NYA8w,23
8
- crackerjack/.pre-commit-config-ai.yaml,sha256=K8xXKMJcdhfXOk24L4XpK7H8YlvnZfOh4NVA6qvOz8I,3319
9
- crackerjack/.pre-commit-config.yaml,sha256=kEaFx4gHzjpyB24ScoBIsvQ9I8GL4RDDB8tyRtr0_aA,2643
10
- crackerjack/.pytest_cache/.gitignore,sha256=Ptcxtl0GFQwTji2tsL4Gl1UIiKa0frjEXsya26i46b0,37
11
- crackerjack/.pytest_cache/CACHEDIR.TAG,sha256=N9yI75oKvt2-gQU6bdj9-xOvthMEXqHrSlyBWnSjveQ,191
12
- crackerjack/.pytest_cache/README.md,sha256=c_1vzN2ALEGaay2YPWwxc7fal1WKxLWJ7ewt_kQ9ua0,302
13
- crackerjack/.pytest_cache/v/cache/nodeids,sha256=T1PNoYwrqgwDVLtfmj7L5e0Sq02OEbqHPC8RFhICuUU,2
14
- crackerjack/.pytest_cache/v/cache/stepwise,sha256=T1PNoYwrqgwDVLtfmj7L5e0Sq02OEbqHPC8RFhICuUU,2
15
- crackerjack/.ruff_cache/.gitignore,sha256=aEiIwOuxfzdCmLZe4oB1JsBmCUxwG8x-u-HBCV9JT8E,1
16
- crackerjack/.ruff_cache/0.1.11/3256171999636029978,sha256=-RLDsRf5uj09SyFQVzjwQ1HkTxjIRxNLLE24SEJxD4g,248
17
- crackerjack/.ruff_cache/0.1.14/602324811142551221,sha256=HIYvldb69IHdMzquAA8JpzU2RDT9shEB_dPvzyeFZ_g,248
18
- crackerjack/.ruff_cache/0.1.4/10355199064880463147,sha256=kmqNg5WySQYPeAqa5elfaV7yjdWQ1xAImpeuzglAqnE,248
19
- crackerjack/.ruff_cache/0.1.6/15140459877605758699,sha256=oQy5boAXeskdm5M0Abh_nyBtitWj5N5wtx_4gsDgu7c,248
20
- crackerjack/.ruff_cache/0.1.7/1790508110482614856,sha256=De7Puq32XF0925xrGehWSKX6cw5Wi2bpt1cnqh__f54,248
21
- crackerjack/.ruff_cache/0.1.9/17041001205004563469,sha256=tKP_k8HaHhQJyrHbDfJ93kM7vahjrU8cKQ1f_-OUzZY,248
22
- crackerjack/.ruff_cache/0.11.11/18187162184424859798,sha256=rx6CoDveth9JeurkrEgbDB4U0esMrGQ7pwIi5VnKEdo,153
23
- crackerjack/.ruff_cache/0.11.12/16869036553936192448,sha256=pYYUCDrYh7fPq8xkFLxvmz9gA55kTuRbMAmbVU4-Eco,153
24
- crackerjack/.ruff_cache/0.11.12/1867267426380906393,sha256=2w4M0Lrjd9flwuq6uJxehTbm7FVUcK5sL2sz1gS2Yvo,256
25
- crackerjack/.ruff_cache/0.11.12/4240757255861806333,sha256=uph5uIRG-XnF7ywAEcCxqqgIkWALPCvJFcwCgnNfTI4,77
26
- crackerjack/.ruff_cache/0.11.12/4441409093023629623,sha256=eHrESew3XCFJ2WqmKvtGLO1r4mY5Q_mv7yGlDmM1sSc,153
27
- crackerjack/.ruff_cache/0.11.13/1867267426380906393,sha256=XRpZCU9UqBNycXaVuXEfG6ReYZREBUUjwV46ibS7dlk,256
28
- crackerjack/.ruff_cache/0.11.13/4240757255861806333,sha256=l35TwAYyTusgJgyePvfP4_CCllPs1sWapEiLFZw8chQ,83
29
- crackerjack/.ruff_cache/0.11.2/4070660268492669020,sha256=FTRTUmvj6nZw_QQBp_WHI-h3_iqRejzL39api-9wTvs,224
30
- crackerjack/.ruff_cache/0.11.3/9818742842212983150,sha256=U-4mT__a-OljovvAJvv5M6X7TCMa3dReLXx3kTNGgwU,224
31
- crackerjack/.ruff_cache/0.11.4/9818742842212983150,sha256=QF9j6-3MH_d0pDNotdbF2hlqCL66SxN8OLVKR3PZyZU,224
32
- crackerjack/.ruff_cache/0.11.6/3557596832929915217,sha256=yR2iXWDkSHVRw2eTiaCE8Eh34JPRUGc8vE3HYEEBk9k,224
33
- crackerjack/.ruff_cache/0.11.7/10386934055395314831,sha256=lBNwN5zAgM4OzbkXIOzCczUtfooATrD10htj9ASlFkc,224
34
- crackerjack/.ruff_cache/0.11.7/3557596832929915217,sha256=fKlwUbsvT3YIKV6UR-aA_i64lLignWeVfVu-MMmVbU0,207
35
- crackerjack/.ruff_cache/0.11.8/530407680854991027,sha256=xAMAL3Vu_HR6M-h5ojCTaak0By5ii8u-14pXULLgLqw,224
36
- crackerjack/.ruff_cache/0.12.0/5056746222905752453,sha256=MqrIT5qymJcgAOBZyn-TvYoGCFfDFCgN9IwSULq8n14,256
37
- crackerjack/.ruff_cache/0.12.1/5056746222905752453,sha256=ya4ZTWCPzijLvXKGnOjRiQC3IdQhyeH7XJ6rwWwxW9g,256
38
- crackerjack/.ruff_cache/0.12.2/5056746222905752453,sha256=3mdGHbtATunuFEnjBCdX9N0CvGEQzv30tj1wEYmEp6I,256
39
- crackerjack/.ruff_cache/0.12.3/5056746222905752453,sha256=Fg5KMq8c0ag2Vh3MTPrFs72njUsXZmjH2y0G_-lQGtM,256
40
- crackerjack/.ruff_cache/0.2.0/10047773857155985907,sha256=j9LNa_RQ4Plor7go1uTYgz17cEENKvZQ-dP6b9MX0ik,248
41
- crackerjack/.ruff_cache/0.2.1/8522267973936635051,sha256=u_aPBMibtAp_iYvLwR88GMAECMcIgHezxMyuapmU2P4,248
42
- crackerjack/.ruff_cache/0.2.2/18053836298936336950,sha256=Xb_ebP0pVuUfSqPEZKlhQ70so_vqkEfMYpuHQ06iR5U,248
43
- crackerjack/.ruff_cache/0.3.0/12548816621480535786,sha256=TAZaMTWC-6O3eZXnWVsQgaKtVPew0QbrAFOWz96hK6g,248
44
- crackerjack/.ruff_cache/0.3.3/11081883392474770722,sha256=S9jhv2NNJwv6bi0JqfBMWcpMktP2A0ikJerra779HKM,248
45
- crackerjack/.ruff_cache/0.3.4/676973378459347183,sha256=qQXG3ByXNuDvpqAhrhjcQVJYeuyS1cBjIxyGgFlT6NI,248
46
- crackerjack/.ruff_cache/0.3.5/16311176246009842383,sha256=1jdzqow8vaK7V6TGKnAFbiL-JUeOUjP8XgYifP1Tg5s,248
47
- crackerjack/.ruff_cache/0.5.7/1493622539551733492,sha256=pSocPQAUIr0jKWiGFCL-guo-Wop2XDXNdJsjylo-ks4,224
48
- crackerjack/.ruff_cache/0.5.7/6231957614044513175,sha256=cpMwivWK0bqQ1V4WO_D1Q-aZarbhf-r4sk4Po8oXZc4,224
49
- crackerjack/.ruff_cache/0.5.7/9932762556785938009,sha256=OrAu-VJZI4ctEycJEplrzI2qXzgaxE5TPvj6IFVQSdw,224
50
- crackerjack/.ruff_cache/0.6.0/11982804814124138945,sha256=2lznSj8cCUgunSBia8roQ-Cj5TBFiSoe0wIl7cDAiY8,224
51
- crackerjack/.ruff_cache/0.6.0/12055761203849489982,sha256=mGzYAukLYQmayZDp4bfHzWpif-GH48e9xi-CMcQDPrM,224
52
- crackerjack/.ruff_cache/0.6.2/1206147804896221174,sha256=Pk8jauJiK81gV1Ox8gp-oUnAsGC2pn_zgOfhPnkM_Yk,224
53
- crackerjack/.ruff_cache/0.6.4/1206147804896221174,sha256=R7O7kFH1eaafsVBj8Tae7ByBULoSlEHITtnjGHZzdo4,224
54
- crackerjack/.ruff_cache/0.6.5/1206147804896221174,sha256=nnb6nWwDVgf1ka9tDmRNyrVOa5D0jWjXGo2SdIOrwE4,224
55
- crackerjack/.ruff_cache/0.6.7/3657366982708166874,sha256=MKU1_a_3BRoP6rKfsIyYJy3lzoXrYcsSw4y8y8ztLb8,224
56
- crackerjack/.ruff_cache/0.6.9/285614542852677309,sha256=6FVRfczYzXuiY_uArIpjA5Tue579y7kFL7hgvebRU2I,224
57
- crackerjack/.ruff_cache/0.7.1/1024065805990144819,sha256=3Sww592NB0PWBNHU_UIqvqgx33GEckEqKoFXxiu2wkA,224
58
- crackerjack/.ruff_cache/0.7.1/285614542852677309,sha256=mOHKRzKoSvW-1sHtqI_LHWRt-mBinJ4rQRtp9Yqzv5I,224
59
- crackerjack/.ruff_cache/0.7.3/16061516852537040135,sha256=AWJR9gmaO7-wpv8mY1homuwI8CrMPI3VrnbXH-wRPlg,224
60
- crackerjack/.ruff_cache/0.8.4/16354268377385700367,sha256=Ksz4X8N6Z1i83N0vV1PxmBRlqgjrtzmDCOg7VBF4baQ,224
61
- crackerjack/.ruff_cache/0.9.10/12813592349865671909,sha256=6yRYi5XvzLtzUymRBm6-DozDE48eJtLmaLGSghgY3Wo,224
62
- crackerjack/.ruff_cache/0.9.10/923908772239632759,sha256=XNakPJR4lyXTBP_I8A0Lpa8zo2WSQhbDnlRKD2lCNrI,224
63
- crackerjack/.ruff_cache/0.9.3/13948373885254993391,sha256=kGhtIkzPUtKAgvlKs3D8j4QM4qG8RhsHrmQJI69Sv3o,224
64
- crackerjack/.ruff_cache/0.9.9/12813592349865671909,sha256=tmr8_vhRD2OxsVuMfbJPdT9fDFX-d5tfC5U9jgziyho,224
65
- crackerjack/.ruff_cache/0.9.9/8843823720003377982,sha256=e4ymkXfQsUg5e_mtO34xTsaTvs1uA3_fI216Qq9qCAM,136
66
- crackerjack/.ruff_cache/CACHEDIR.TAG,sha256=WVMVbX4MVkpCclExbq8m-IcOZIOuIZf5FrYw5Pk-Ma4,43
67
- crackerjack/__init__.py,sha256=8tBSPAru_YDuPpjz05cL7pNbZjYFoRT_agGd_FWa3gY,839
68
- crackerjack/__main__.py,sha256=lEyi83ChuehqEJgUQ6Ib4ByOofvmhi_0M7oFamMC_1I,6407
69
- crackerjack/crackerjack.py,sha256=Ek7DwsaXxbD_15JYaH9p80vWkEPTFY1BvHxIDEyfJAA,47898
70
- crackerjack/errors.py,sha256=Wcv0rXfzV9pHOoXYrhQEjyJd4kUUBbdiY-5M9nI8pDw,4050
71
- crackerjack/interactive.py,sha256=pFItgRUyjOakABLCRz6nIp6_Ycx2LBSeojpYNiTelv0,16126
72
- crackerjack/py313.py,sha256=buYE7LO11Q64ffowEhTZRFQoAGj_8sg3DTlZuv8M9eo,5890
73
- crackerjack/pyproject.toml,sha256=-elPKC69LwnqXesT4iyBPPDAoRcSH4GAiYCL4mY7SRI,4992
74
- crackerjack-0.22.8.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- [console_scripts]
2
-
3
- [gui_scripts]
4
-