crackerjack 0.18.11__py3-none-any.whl → 0.19.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.
@@ -3,12 +3,14 @@ repos:
3
3
  rev: 2.24.2 # a PDM release exposing the hook
4
4
  hooks:
5
5
  - id: pdm-lock-check
6
- # - id: pdm-export
7
- # args: [ '-o', 'requirements.txt', '--without-hashes' ]
8
- # files: ^pdm.lock$
9
6
  - id: pdm-sync
10
7
  additional_dependencies:
11
8
  - keyring
9
+ - repo: https://github.com/astral-sh/uv-pre-commit
10
+ rev: 0.7.9
11
+ hooks:
12
+ - id: uv-lock
13
+ files: ^pyproject\.toml$
12
14
  - repo: https://github.com/pre-commit/pre-commit-hooks
13
15
  rev: v5.0.0
14
16
  hooks:
@@ -22,11 +24,24 @@ repos:
22
24
  name: check-toml
23
25
  - id: check-added-large-files
24
26
  name: check-added-large-files
27
+ - repo: https://github.com/Yelp/detect-secrets
28
+ rev: v1.5.0
29
+ hooks:
30
+ - id: detect-secrets
31
+ exclude: "pdm.lock"
32
+ - repo: https://github.com/abravalheri/validate-pyproject
33
+ rev: v0.24.1
34
+ hooks:
35
+ - id: validate-pyproject
36
+ - repo: https://github.com/tox-dev/pyproject-fmt
37
+ rev: "v2.6.0"
38
+ hooks:
39
+ - id: pyproject-fmt
25
40
  - repo: https://github.com/astral-sh/ruff-pre-commit
26
41
  rev: v0.11.12
27
42
  hooks:
28
- - id: ruff-format
29
43
  - id: ruff-check
44
+ - id: ruff-format
30
45
  - repo: https://github.com/jendrikseipp/vulture
31
46
  rev: 'v2.14'
32
47
  hooks:
@@ -35,10 +50,6 @@ repos:
35
50
  rev: v4.0.3
36
51
  hooks:
37
52
  - id: creosote
38
- - repo: https://github.com/ikamensh/flynt/
39
- rev: '1.0.1'
40
- hooks:
41
- - id: flynt
42
53
  - repo: https://github.com/codespell-project/codespell
43
54
  rev: v2.4.1
44
55
  hooks:
@@ -74,11 +85,6 @@ repos:
74
85
  rev: v1.1.401
75
86
  hooks:
76
87
  - id: pyright
77
- - repo: https://github.com/astral-sh/ruff-pre-commit
78
- rev: v0.11.12
79
- hooks:
80
- - id: ruff-check
81
- - id: ruff-format
82
88
  # - repo: https://github.com/pdoc3/pdoc
83
89
  # rev: master
84
90
  # hooks:
crackerjack/__main__.py CHANGED
@@ -32,6 +32,8 @@ class Options(BaseModel):
32
32
  clean: bool = False
33
33
  test: bool = False
34
34
  benchmark: bool = False
35
+ benchmark_regression: bool = False
36
+ benchmark_regression_threshold: float = 5.0
35
37
  all: BumpOption | None = None
36
38
  ai_agent: bool = False
37
39
  create_pr: bool = False
@@ -90,6 +92,16 @@ cli_options = {
90
92
  "--benchmark",
91
93
  help="Run tests in benchmark mode (disables parallel execution).",
92
94
  ),
95
+ "benchmark_regression": typer.Option(
96
+ False,
97
+ "--benchmark-regression",
98
+ help="Fail tests if benchmarks regress beyond threshold.",
99
+ ),
100
+ "benchmark_regression_threshold": typer.Option(
101
+ 5.0,
102
+ "--benchmark-regression-threshold",
103
+ help="Maximum allowed performance regression percentage (default: 5.0%).",
104
+ ),
93
105
  "skip_hooks": typer.Option(
94
106
  False,
95
107
  "-s",
@@ -132,6 +144,10 @@ def main(
132
144
  clean: bool = cli_options["clean"],
133
145
  test: bool = cli_options["test"],
134
146
  benchmark: bool = cli_options["benchmark"],
147
+ benchmark_regression: bool = cli_options["benchmark_regression"],
148
+ benchmark_regression_threshold: float = cli_options[
149
+ "benchmark_regression_threshold"
150
+ ],
135
151
  skip_hooks: bool = cli_options["skip_hooks"],
136
152
  create_pr: bool = cli_options["create_pr"],
137
153
  ai_agent: bool = cli_options["ai_agent"],
@@ -148,6 +164,8 @@ def main(
148
164
  clean=clean,
149
165
  test=test,
150
166
  benchmark=benchmark,
167
+ benchmark_regression=benchmark_regression,
168
+ benchmark_regression_threshold=benchmark_regression_threshold,
151
169
  skip_hooks=skip_hooks,
152
170
  all=all,
153
171
  ai_agent=ai_agent,
@@ -39,7 +39,9 @@ class OptionsProtocol(t.Protocol):
39
39
  update_precommit: bool
40
40
  clean: bool
41
41
  test: bool
42
- benchmark: bool = False
42
+ benchmark: bool
43
+ benchmark_regression: bool
44
+ benchmark_regression_threshold: float
43
45
  publish: t.Any | None
44
46
  bump: t.Any | None
45
47
  all: t.Any | None
@@ -295,10 +297,10 @@ class ConfigManager:
295
297
  for k, v in {
296
298
  x: self.swap_package_name(y)
297
299
  for x, y in value.items()
298
- if isinstance(y, (str, list)) and "crackerjack" in str(y)
300
+ if isinstance(y, str | list) and "crackerjack" in str(y)
299
301
  }.items():
300
302
  settings[setting][k] = v
301
- elif isinstance(value, (str, list)) and "crackerjack" in str(value):
303
+ elif isinstance(value, str | list) and "crackerjack" in str(value):
302
304
  value = self.swap_package_name(value)
303
305
  settings[setting] = value
304
306
  if setting in (
@@ -492,9 +494,27 @@ class Crackerjack:
492
494
  self.code_cleaner.clean_files(tests_dir)
493
495
 
494
496
  def _prepare_pytest_command(self, options: OptionsProtocol) -> list[str]:
497
+ """Prepare pytest command with appropriate options.
498
+
499
+ Configures pytest command with:
500
+ - Standard options for formatting and output control
501
+ - Benchmark options when benchmark mode is enabled
502
+ - Benchmark regression options when regression testing is enabled
503
+ - Parallel execution via xdist for non-benchmark tests
504
+
505
+ Benchmark and parallel execution (xdist) are incompatible, so the command
506
+ automatically disables parallelism when benchmarks are enabled.
507
+
508
+ Args:
509
+ options: Command options with benchmark and test settings
510
+
511
+ Returns:
512
+ List of command-line arguments for pytest
513
+ """
495
514
  test = ["pytest"]
496
515
  if options.verbose:
497
516
  test.append("-v")
517
+
498
518
  test.extend(
499
519
  [
500
520
  "--capture=fd", # Capture stdout/stderr at file descriptor level
@@ -505,9 +525,27 @@ class Crackerjack:
505
525
  "--timeout=60", # 1-minute timeout for tests
506
526
  ]
507
527
  )
508
- # Add benchmark flag if enabled (disables parallel execution)
509
- if options.benchmark:
510
- test.append("--benchmark")
528
+
529
+ # Benchmarks and parallel testing are incompatible
530
+ # Handle them mutually exclusively
531
+ if options.benchmark or options.benchmark_regression:
532
+ # When running benchmarks, avoid parallel execution
533
+ # and apply specific benchmark options
534
+ if options.benchmark:
535
+ test.append("--benchmark")
536
+
537
+ # Add benchmark regression testing options if enabled
538
+ if options.benchmark_regression:
539
+ test.extend(
540
+ [
541
+ "--benchmark-regression",
542
+ f"--benchmark-regression-threshold={options.benchmark_regression_threshold}",
543
+ ]
544
+ )
545
+ else:
546
+ # No benchmarks - use parallel execution for speed
547
+ test.append("-xvs")
548
+
511
549
  return test
512
550
 
513
551
  def _setup_test_environment(self) -> None:
@@ -1,146 +1,174 @@
1
- [tool.pytest.ini_options]
2
- addopts = "--cov=crackerjack --cov-report=term --timeout=120 --timeout-method=thread -n auto"
3
- asyncio_default_fixture_loop_scope = "function"
4
- python_files = ["test_*.py", "*_test.py"]
5
- asyncio_mode = "auto"
6
- testpaths = ["tests", "crackerjack"]
7
- python_classes = ["Test*"]
8
- python_functions = ["test_*"]
9
- markers = [
10
- "unit: marks test as a unit test",
11
- ]
12
-
13
- [tool.coverage.run]
14
- branch = false
15
- source = ["crackerjack"]
16
- data_file = ".coverage"
17
- parallel = false
18
- omit = [
19
- "*/tests/*",
20
- "*/site-packages/*",
21
- "*/__pycache__/*",
22
- "*/__init__.py",
23
- "*/_version.py", "*/conftest.py", "*/test_*.py", "*/_test.py"
24
- ]
1
+ [build-system]
2
+ build-backend = "pdm.backend"
3
+ requires = [ "pdm-backend" ]
25
4
 
26
- [tool.coverage.report]
27
- exclude_also = [
28
- "pragma: no cover",
29
- "def __repr__",
30
- "raise NotImplementedError",
31
- "if __name__ == .__main__.:",
32
- "pass",
33
- "raise ImportError",
34
- "except ImportError",
35
- "def __str__",
36
- "@abstractmethod",
37
- ]
38
- ignore_errors = false
5
+ [project]
6
+ name = "crackerjack"
7
+ version = "0.18.12"
8
+ description = "Crackerjack: code quality toolkit"
9
+ readme = "README.md"
10
+ keywords = [
11
+ "bandit",
12
+ "black",
13
+ "creosote",
14
+ "mypy",
15
+ "pyright",
16
+ "pytest",
17
+ "refurb",
18
+ "ruff",
19
+ ]
20
+ license.text = "BSD-3-CLAUSE"
21
+ maintainers = [
22
+ { name = "lesleslie", email = "les@wedgwoodwebworks.com" },
23
+ ]
39
24
 
40
- [tool.codespell]
41
- skip = "*/data/*"
42
- quiet-level = 3
43
- ignore-words-list = "crate,uptodate,nd"
25
+ authors = [
26
+ { name = "lesleslie", email = "les@wedgwoodwebworks.com" },
27
+ ]
28
+ requires-python = ">=3.13"
29
+ classifiers = [
30
+ "Development Status :: 4 - Beta",
31
+ "Environment :: Console",
32
+ "License :: OSI Approved :: BSD License",
33
+ "Operating System :: POSIX",
34
+ "Programming Language :: Python",
35
+ "Programming Language :: Python :: 3 :: Only",
36
+ "Programming Language :: Python :: 3.13",
37
+ "Topic :: Software Development :: Libraries :: Python Modules",
38
+ "Topic :: Software Development :: Quality Assurance",
39
+ "Topic :: Software Development :: Testing",
40
+ "Topic :: Utilities",
41
+ "Typing :: Typed",
42
+ ]
43
+ dependencies = [
44
+ "autotyping>=24.9",
45
+ "pdm>=2.24.2",
46
+ "pdm-bump>=0.9.12",
47
+ "pre-commit>=4.2",
48
+ "pydantic>=2.11.5",
49
+ "pytest>=8.3.5",
50
+ "pytest-asyncio>=1",
51
+ "pytest-benchmark>=5.1",
52
+ "pytest-cov>=6.1.1",
53
+ "pytest-mock>=3.14.1",
54
+ "pytest-timeout>=2.4",
55
+ "pytest-xdist>=3.7",
56
+ "rich>=14",
57
+ "tomli-w>=1.2",
58
+ "typer>=0.16",
59
+ "uv>=0.7.9",
60
+ ]
61
+ urls.documentation = "https://github.com/lesleslie/crackerjack"
62
+ urls.homepage = "https://github.com/lesleslie/crackerjack"
63
+ urls.repository = "https://github.com/lesleslie/crackerjack"
44
64
 
45
65
  [tool.ruff]
46
- line-length = 88
47
66
  target-version = "py313"
67
+ line-length = 88
48
68
  fix = true
69
+ unsafe-fixes = true
70
+
49
71
  show-fixes = true
50
72
  output-format = "full"
51
- unsafe-fixes = true
73
+ format.docstring-code-format = true
74
+ lint.extend-select = [
75
+ "C901",
76
+ "D",
77
+ "F", # pyflakes
78
+ "I",
79
+ "UP", # pyupgrade (includes F-string conversion)
80
+ ]
81
+ lint.ignore = [
82
+ "D100",
83
+ "D101",
84
+ "D102",
85
+ "D103",
86
+ "D104",
87
+ "D105",
88
+ "D106",
89
+ "D107",
90
+ "F821",
91
+ ]
92
+ lint.fixable = [ "ALL" ]
93
+ lint.unfixable = [ ]
94
+ lint.isort.no-lines-before = [
95
+ "first-party",
96
+ ]
97
+ lint.mccabe.max-complexity = 13
98
+ lint.pydocstyle.convention = "google"
52
99
 
53
- [tool.ruff.format]
54
- docstring-code-format = true
100
+ [tool.codespell]
101
+ skip = "*/data/*"
102
+ quiet-level = 3
103
+ ignore-words-list = "crate,uptodate,nd"
55
104
 
56
- [tool.ruff.lint]
57
- ignore = [
58
- "F821",
59
- "D100",
60
- "D101",
61
- "D102",
62
- "D103",
63
- "D104",
64
- "D105",
65
- "D106",
66
- "D107",
67
- ]
68
- extend-select = [
69
- "I",
70
- "C901",
71
- "D",
72
- ]
73
- fixable = ["ALL"]
74
- unfixable = []
105
+ [tool.pytest.ini_options]
106
+ # Core pytest configuration
107
+ asyncio_mode = "auto"
108
+ asyncio_default_fixture_loop_scope = "function"
109
+ python_files = [ "test_*.py", "*_test.py" ]
110
+ testpaths = [ "tests", "crackerjack" ]
111
+ python_classes = [ "Test*" ]
112
+ python_functions = [ "test_*" ]
75
113
 
76
- [tool.ruff.lint.isort]
77
- no-lines-before = [
78
- "first-party",
114
+ # Markers
115
+ markers = [
116
+ "unit: marks test as a unit test",
117
+ "benchmark: mark test as a benchmark (disables parallel execution)",
79
118
  ]
80
119
 
81
- [tool.ruff.lint.mccabe]
82
- max-complexity = 13
120
+ # Default timeout settings
121
+ timeout = 60
122
+ timeout_method = "thread"
83
123
 
84
- [tool.ruff.lint.pydocstyle]
85
- convention = "google"
124
+ # Test command options
125
+ addopts = "--cov=crackerjack --cov-report=term --cov-fail-under=80"
86
126
 
87
- [tool.vulture]
88
- min_confidence = 86
89
- paths = ["crackerjack",]
90
- ignore_names = ["cls"]
127
+ [tool.pytest.benchmark]
128
+ disable_gc = true
129
+ warmup = false
130
+ warmup_iterations = 0
91
131
 
92
- [tool.creosote]
93
- paths = [
94
- "crackerjack",
95
- ]
96
- deps-file = "pyproject.toml"
97
- exclude-deps = [
98
- "pdm-bump",
99
- "autotyping",
100
- "pre-commit",
101
- "pytest",
102
- "pytest-asyncio",
103
- "pytest-cov",
104
- "pytest-mock",
105
- "pytest-xdist",
106
- "pdm",
107
- "pyfiglet",
108
- "pyyaml",
109
- "uv",
110
- "tomli-w",
111
- "google-crc32c",
112
- "pytest-timeout",
132
+ [tool.coverage.run]
133
+ branch = false
134
+ source = [ "crackerjack" ]
135
+ data_file = ".coverage"
136
+ parallel = false
137
+ omit = [
138
+ "*/tests/*",
139
+ "*/site-packages/*",
140
+ "*/__pycache__/*",
141
+ "*/__init__.py",
142
+ "*/_version.py",
143
+ "*/conftest.py",
144
+ "*/test_*.py",
145
+ "*/_test.py",
113
146
  ]
114
147
 
115
- [tool.refurb]
116
- enable_all = true
117
-
118
- [tool.bandit]
119
- target = [
120
- "crackerjack",
121
- ]
122
- skips = [
123
- "B101",
124
- "B301",
125
- "B311",
126
- "B403",
127
- "B404",
128
- "B602",
129
- "B603",
130
- "B607",
131
- "B704",
148
+ [tool.coverage.report]
149
+ exclude_also = [
150
+ "pragma: no cover",
151
+ "def __repr__",
152
+ "raise NotImplementedError",
153
+ "if __name__ == .__main__.:",
154
+ "pass",
155
+ "raise ImportError",
156
+ "except ImportError",
157
+ "def __str__",
158
+ "@abstractmethod",
132
159
  ]
160
+ ignore_errors = false
133
161
 
134
162
  [tool.pyright]
135
163
  verboseOutput = true
136
164
  include = [
137
- "crackerjack",
165
+ "crackerjack",
138
166
  ]
139
167
  exclude = [
140
- "scratch",
168
+ "scratch",
141
169
  ]
142
170
  extraPaths = [
143
- ".venv/lib/python3.13/site-packages/",
171
+ ".venv/lib/python3.13/site-packages/",
144
172
  ]
145
173
  typeCheckingMode = "strict"
146
174
  reportMissingTypeStubs = false
@@ -156,69 +184,50 @@ reportPrivateUsage = false
156
184
  pythonVersion = "3.13"
157
185
  pythonPlatform = "Darwin"
158
186
 
159
- [project]
160
- name = "crackerjack"
161
- version = "0.18.10"
162
- description = "Default template for PDM package"
163
- requires-python = ">=3.13"
164
- readme = "README.md"
165
- keywords = [
166
- "black",
167
- "ruff",
168
- "mypy",
169
- "creosote",
170
- "refurb",
171
- "pyright",
172
- "bandit",
173
- "pytest",
174
- ]
175
- classifiers = [
176
- "Environment :: Console",
177
- "Operating System :: POSIX",
178
- "Programming Language :: Python",
179
- "Programming Language :: Python :: 3.13",
180
- "Development Status :: 4 - Beta",
181
- "Topic :: Software Development :: Libraries :: Python Modules",
182
- "Topic :: Software Development :: Quality Assurance",
183
- "Topic :: Software Development :: Testing",
184
- "Topic :: Utilities",
185
- "Topic :: Software Development :: Libraries :: Python Modules",
186
- "License :: OSI Approved :: BSD License",
187
- "Typing :: Typed",
188
- ]
189
- dependencies = [
190
- "autotyping>=24.9.0",
191
- "pre-commit>=4.2.0",
192
- "pytest>=8.3.5",
193
- "pydantic>=2.11.5",
194
- "pdm-bump>=0.9.12",
195
- "pdm>=2.24.2",
196
- "uv>=0.7.9",
197
- "pytest-cov>=6.1.1",
198
- "pytest-mock>=3.14.1",
199
- "tomli-w>=1.2.0",
200
- "pytest-asyncio>=1.0.0",
201
- "rich>=14.0.0",
202
- "typer>=0.16.0",
203
- "pytest-timeout>=2.4.0",
204
- "pytest-xdist>=3.7.0",
205
- ]
206
- authors = [
207
- { name = "lesleslie", email = "les@wedgwoodwebworks.com" },
187
+ [tool.vulture]
188
+ min_confidence = 86
189
+ paths = [ "crackerjack" ]
190
+ ignore_names = [ "cls" ]
191
+
192
+ [tool.creosote]
193
+ paths = [
194
+ "crackerjack",
208
195
  ]
209
- maintainers = [
210
- { name = "lesleslie", email = "les@wedgwoodwebworks.com" },
196
+ deps-file = "pyproject.toml"
197
+ exclude-deps = [
198
+ "pdm-bump",
199
+ "autotyping",
200
+ "pre-commit",
201
+ "pytest",
202
+ "pytest-asyncio",
203
+ "pytest-cov",
204
+ "pytest-mock",
205
+ "pytest-xdist",
206
+ "pytest-benchmark",
207
+ "pdm",
208
+ "pyfiglet",
209
+ "pyyaml",
210
+ "uv",
211
+ "tomli-w",
212
+ "google-crc32c",
213
+ "pytest-timeout",
211
214
  ]
212
215
 
213
- [project.license]
214
- text = "BSD-3-CLAUSE"
215
-
216
- [project.urls]
217
- homepage = "https://github.com/lesleslie/crackerjack"
218
- documentation = "https://github.com/lesleslie/crackerjack"
219
- repository = "https://github.com/lesleslie/crackerjack"
220
-
216
+ [tool.refurb]
217
+ enable_all = true
221
218
 
222
- [build-system]
223
- requires = ["pdm-backend"]
224
- build-backend = "pdm.backend"
219
+ [tool.bandit]
220
+ target = [
221
+ "crackerjack",
222
+ ]
223
+ skips = [
224
+ "B101",
225
+ "B301",
226
+ "B311",
227
+ "B403",
228
+ "B404",
229
+ "B602",
230
+ "B603",
231
+ "B607",
232
+ "B704",
233
+ ]
@@ -1,42 +1,43 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crackerjack
3
- Version: 0.18.11
4
- Summary: Default template for PDM package
5
- Keywords: black,ruff,mypy,creosote,refurb,pyright,bandit,pytest
3
+ Version: 0.19.0
4
+ Summary: Crackerjack: code quality toolkit
5
+ Keywords: bandit,black,creosote,mypy,pyright,pytest,refurb,ruff
6
6
  Author-Email: lesleslie <les@wedgwoodwebworks.com>
7
7
  Maintainer-Email: lesleslie <les@wedgwoodwebworks.com>
8
8
  License: BSD-3-CLAUSE
9
+ Classifier: Development Status :: 4 - Beta
9
10
  Classifier: Environment :: Console
11
+ Classifier: License :: OSI Approved :: BSD License
10
12
  Classifier: Operating System :: POSIX
11
13
  Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3 :: Only
12
15
  Classifier: Programming Language :: Python :: 3.13
13
- Classifier: Development Status :: 4 - Beta
14
16
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
17
  Classifier: Topic :: Software Development :: Quality Assurance
16
18
  Classifier: Topic :: Software Development :: Testing
17
19
  Classifier: Topic :: Utilities
18
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
- Classifier: License :: OSI Approved :: BSD License
20
20
  Classifier: Typing :: Typed
21
- Project-URL: homepage, https://github.com/lesleslie/crackerjack
22
21
  Project-URL: documentation, https://github.com/lesleslie/crackerjack
22
+ Project-URL: homepage, https://github.com/lesleslie/crackerjack
23
23
  Project-URL: repository, https://github.com/lesleslie/crackerjack
24
24
  Requires-Python: >=3.13
25
- Requires-Dist: autotyping>=24.9.0
26
- Requires-Dist: pre-commit>=4.2.0
27
- Requires-Dist: pytest>=8.3.5
28
- Requires-Dist: pydantic>=2.11.5
29
- Requires-Dist: pdm-bump>=0.9.12
25
+ Requires-Dist: autotyping>=24.9
30
26
  Requires-Dist: pdm>=2.24.2
31
- Requires-Dist: uv>=0.7.9
27
+ Requires-Dist: pdm-bump>=0.9.12
28
+ Requires-Dist: pre-commit>=4.2
29
+ Requires-Dist: pydantic>=2.11.5
30
+ Requires-Dist: pytest>=8.3.5
31
+ Requires-Dist: pytest-asyncio>=1
32
+ Requires-Dist: pytest-benchmark>=5.1
32
33
  Requires-Dist: pytest-cov>=6.1.1
33
34
  Requires-Dist: pytest-mock>=3.14.1
34
- Requires-Dist: tomli-w>=1.2.0
35
- Requires-Dist: pytest-asyncio>=1.0.0
36
- Requires-Dist: rich>=14.0.0
37
- Requires-Dist: typer>=0.16.0
38
- Requires-Dist: pytest-timeout>=2.4.0
39
- Requires-Dist: pytest-xdist>=3.7.0
35
+ Requires-Dist: pytest-timeout>=2.4
36
+ Requires-Dist: pytest-xdist>=3.7
37
+ Requires-Dist: rich>=14
38
+ Requires-Dist: tomli-w>=1.2
39
+ Requires-Dist: typer>=0.16
40
+ Requires-Dist: uv>=0.7.9
40
41
  Description-Content-Type: text/markdown
41
42
 
42
43
  # Crackerjack: Elevate Your Python Development
@@ -176,6 +177,44 @@ Crackerjack projects adhere to these guidelines:
176
177
  - **Clear Code:** Avoid overly complex code.
177
178
  - **Modular:** Functions should do one thing well.
178
179
 
180
+ ## Testing Features
181
+
182
+ Crackerjack provides advanced testing capabilities powered by pytest:
183
+
184
+ ### Standard Testing
185
+
186
+ - **Parallel Test Execution:** Tests run in parallel by default using pytest-xdist for faster execution
187
+ - **Timeout Protection:** All tests have a default 60-second timeout to prevent hanging tests
188
+ - **Coverage Reports:** Automatically generates test coverage reports with configurable thresholds
189
+
190
+ ### Benchmark Testing
191
+
192
+ Crackerjack includes benchmark testing capabilities:
193
+
194
+ - **Performance Measurement:** Run tests with `--benchmark` to measure execution time and performance
195
+ - **Regression Testing:** Use `--benchmark-regression` to detect performance regressions
196
+ - **Configurable Thresholds:** Set custom regression thresholds with `--benchmark-regression-threshold`
197
+ - **Compatibility Management:** Automatically disables parallel execution when running benchmarks
198
+ - **CI Integration:** Track performance across commits with benchmark history
199
+
200
+ When benchmarks are run, Crackerjack:
201
+ 1. Disables parallel test execution (as pytest-benchmark is incompatible with pytest-xdist)
202
+ 2. Configures the pytest-benchmark plugin with optimized settings
203
+ 3. Compares benchmark results against previous runs when regression testing is enabled
204
+ 4. Fails tests if performance decreases beyond the specified threshold
205
+
206
+ Example benchmark usage:
207
+ ```bash
208
+ # Run benchmarks
209
+ python -m crackerjack -t --benchmark
210
+
211
+ # Run benchmarks with regression testing (fail if >5% slower)
212
+ python -m crackerjack -t --benchmark-regression
213
+
214
+ # Run benchmarks with custom regression threshold (10%)
215
+ python -m crackerjack -t --benchmark-regression --benchmark-regression-threshold=10.0
216
+ ```
217
+
179
218
  ## Installation
180
219
 
181
220
  1. **Python:** Ensure you have Python 3.13 installed.
@@ -226,6 +265,9 @@ class MyOptions:
226
265
  # Process options
227
266
  self.clean = True # Clean code (remove docstrings, comments, etc.)
228
267
  self.test = True # Run tests using pytest
268
+ self.benchmark = False # Run tests in benchmark mode
269
+ self.benchmark_regression = False # Fail tests if benchmarks regress beyond threshold
270
+ self.benchmark_regression_threshold = 5.0 # Threshold percentage for benchmark regression
229
271
  self.skip_hooks = False # Skip running pre-commit hooks
230
272
 
231
273
  # Version and publishing options
@@ -266,6 +308,9 @@ runner.process(MyOptions())
266
308
  - `-s`, `--skip-hooks`: Skip running pre-commit hooks (useful with `-t`).
267
309
  - `-x`, `--clean`: Clean code by removing docstrings, line comments, and extra whitespace.
268
310
  - `-t`, `--test`: Run tests using `pytest`.
311
+ - `--benchmark`: Run tests in benchmark mode (disables parallel execution).
312
+ - `--benchmark-regression`: Fail tests if benchmarks regress beyond threshold.
313
+ - `--benchmark-regression-threshold`: Set threshold percentage for benchmark regression (default 5.0%).
269
314
  - `-a`, `--all`: Run with `-x -t -p <micro|minor|major> -c` development options.
270
315
  - `--ai-agent`: Enable AI agent mode with structured output (see [AI Agent Integration](#ai-agent-integration)).
271
316
  - `--help`: Display help.
@@ -1,11 +1,11 @@
1
- crackerjack-0.18.11.dist-info/METADATA,sha256=ytW5hRPJ4ifpY8kBGzC7c9WIu2pBZ0toafas9yGayvU,17891
2
- crackerjack-0.18.11.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- crackerjack-0.18.11.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
- crackerjack-0.18.11.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
1
+ crackerjack-0.19.0.dist-info/METADATA,sha256=RM8Yv-Qp7IFTbgvQlNakwXnpvU_fSGG_xy-HhcDFdFM,20079
2
+ crackerjack-0.19.0.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ crackerjack-0.19.0.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
+ crackerjack-0.19.0.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
5
5
  crackerjack/.gitignore,sha256=oho3dNx7a7y36_y9AsalCkssU4in0MMsNAANWdc-h1c,153
6
6
  crackerjack/.libcst.codemod.yaml,sha256=a8DlErRAIPV1nE6QlyXPAzTOgkB24_spl2E9hphuf5s,772
7
7
  crackerjack/.pdm.toml,sha256=dZe44HRcuxxCFESGG8SZIjmc-cGzSoyK3Hs6t4NYA8w,23
8
- crackerjack/.pre-commit-config.yaml,sha256=n68rmT6B0wMEGCKdAUALFSGmz5V2Djf4CAIrZVW1HLs,2470
8
+ crackerjack/.pre-commit-config.yaml,sha256=QSc25WQTksQ199Ww21Y3IwlxDFhJR52RD0KNldSQoGs,2621
9
9
  crackerjack/.pytest_cache/.gitignore,sha256=Ptcxtl0GFQwTji2tsL4Gl1UIiKa0frjEXsya26i46b0,37
10
10
  crackerjack/.pytest_cache/CACHEDIR.TAG,sha256=N9yI75oKvt2-gQU6bdj9-xOvthMEXqHrSlyBWnSjveQ,191
11
11
  crackerjack/.pytest_cache/README.md,sha256=c_1vzN2ALEGaay2YPWwxc7fal1WKxLWJ7ewt_kQ9ua0,302
@@ -19,7 +19,8 @@ crackerjack/.ruff_cache/0.1.6/15140459877605758699,sha256=oQy5boAXeskdm5M0Abh_ny
19
19
  crackerjack/.ruff_cache/0.1.7/1790508110482614856,sha256=De7Puq32XF0925xrGehWSKX6cw5Wi2bpt1cnqh__f54,248
20
20
  crackerjack/.ruff_cache/0.1.9/17041001205004563469,sha256=tKP_k8HaHhQJyrHbDfJ93kM7vahjrU8cKQ1f_-OUzZY,248
21
21
  crackerjack/.ruff_cache/0.11.11/18187162184424859798,sha256=rx6CoDveth9JeurkrEgbDB4U0esMrGQ7pwIi5VnKEdo,153
22
- crackerjack/.ruff_cache/0.11.12/16869036553936192448,sha256=uxsncFYKNPwSycx7qLs0qMoQV0KPcF7bcxVAYSnapKU,153
22
+ crackerjack/.ruff_cache/0.11.12/16869036553936192448,sha256=pYYUCDrYh7fPq8xkFLxvmz9gA55kTuRbMAmbVU4-Eco,153
23
+ crackerjack/.ruff_cache/0.11.12/4441409093023629623,sha256=4lugbLzZFizppHUBc5ExlwJhS3D0qYg3nTYZ6vDXHRM,153
23
24
  crackerjack/.ruff_cache/0.11.2/4070660268492669020,sha256=FTRTUmvj6nZw_QQBp_WHI-h3_iqRejzL39api-9wTvs,224
24
25
  crackerjack/.ruff_cache/0.11.3/9818742842212983150,sha256=U-4mT__a-OljovvAJvv5M6X7TCMa3dReLXx3kTNGgwU,224
25
26
  crackerjack/.ruff_cache/0.11.4/9818742842212983150,sha256=QF9j6-3MH_d0pDNotdbF2hlqCL66SxN8OLVKR3PZyZU,224
@@ -55,7 +56,7 @@ crackerjack/.ruff_cache/0.9.9/12813592349865671909,sha256=tmr8_vhRD2OxsVuMfbJPdT
55
56
  crackerjack/.ruff_cache/0.9.9/8843823720003377982,sha256=e4ymkXfQsUg5e_mtO34xTsaTvs1uA3_fI216Qq9qCAM,136
56
57
  crackerjack/.ruff_cache/CACHEDIR.TAG,sha256=WVMVbX4MVkpCclExbq8m-IcOZIOuIZf5FrYw5Pk-Ma4,43
57
58
  crackerjack/__init__.py,sha256=r9SuEjHUrW99hFWifRk4ofmYPSgf9rblcnzqhdV5bP0,157
58
- crackerjack/__main__.py,sha256=PWsTFt2EADcpLcqKMx845Ik-fBF_CkCcVIkAD-VkS6I,4813
59
- crackerjack/crackerjack.py,sha256=qt11vI8tIofKOsZiaHi1I_q-UY18qgKthve3dEfhis8,33738
60
- crackerjack/pyproject.toml,sha256=crpeF_U-y_I9x8W6b2vD8VBfulyegarDOwhXHf2m-Nw,4424
61
- crackerjack-0.18.11.dist-info/RECORD,,
59
+ crackerjack/__main__.py,sha256=MTVu9nxSIkMgUBIlieq561PX-ts1HaNMsFaTWdLUqz0,5561
60
+ crackerjack/crackerjack.py,sha256=8sHtYljfHJy5mpC6gHAwKw5686yG8050CFzk3Ohprd4,35167
61
+ crackerjack/pyproject.toml,sha256=f9SbyizS6_z5if4q2lskVzlp_8CrDfp4kyWBWmYT9Y8,4535
62
+ crackerjack-0.19.0.dist-info/RECORD,,