crackerjack 0.14.9__tar.gz → 0.15.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {crackerjack-0.14.9 → crackerjack-0.15.0}/PKG-INFO +63 -12
  2. {crackerjack-0.14.9 → crackerjack-0.15.0}/README.md +62 -11
  3. crackerjack-0.15.0/crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  4. crackerjack-0.15.0/crackerjack/__init__.py +5 -0
  5. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/__main__.py +12 -15
  6. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/crackerjack.py +48 -13
  7. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/pyproject.toml +1 -1
  8. {crackerjack-0.14.9 → crackerjack-0.15.0}/pyproject.toml +1 -1
  9. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/test_crackerjack.py +1 -1
  10. crackerjack-0.15.0/tests/test_crackerjack_runner.py +126 -0
  11. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/test_main.py +70 -67
  12. crackerjack-0.14.9/crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
  13. crackerjack-0.14.9/crackerjack/__init__.py +0 -5
  14. {crackerjack-0.14.9 → crackerjack-0.15.0}/LICENSE +0 -0
  15. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.coverage +0 -0
  16. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.gitignore +0 -0
  17. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.libcst.codemod.yaml +0 -0
  18. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pdm.toml +0 -0
  19. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pre-commit-config.yaml +0 -0
  20. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pytest_cache/.gitignore +0 -0
  21. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pytest_cache/CACHEDIR.TAG +0 -0
  22. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pytest_cache/README.md +0 -0
  23. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pytest_cache/v/cache/nodeids +0 -0
  24. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.pytest_cache/v/cache/stepwise +0 -0
  25. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/.gitignore +0 -0
  26. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.11/3256171999636029978 +0 -0
  27. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.14/602324811142551221 +0 -0
  28. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.4/10355199064880463147 +0 -0
  29. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.6/15140459877605758699 +0 -0
  30. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.7/1790508110482614856 +0 -0
  31. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.1.9/17041001205004563469 +0 -0
  32. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.2.0/10047773857155985907 +0 -0
  33. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.2.1/8522267973936635051 +0 -0
  34. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.2.2/18053836298936336950 +0 -0
  35. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.3.0/12548816621480535786 +0 -0
  36. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.3.3/11081883392474770722 +0 -0
  37. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.3.4/676973378459347183 +0 -0
  38. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.3.5/16311176246009842383 +0 -0
  39. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.5.7/1493622539551733492 +0 -0
  40. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.5.7/6231957614044513175 +0 -0
  41. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.5.7/9932762556785938009 +0 -0
  42. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.0/11982804814124138945 +0 -0
  43. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.0/12055761203849489982 +0 -0
  44. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.2/1206147804896221174 +0 -0
  45. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.4/1206147804896221174 +0 -0
  46. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.5/1206147804896221174 +0 -0
  47. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.7/3657366982708166874 +0 -0
  48. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.6.9/285614542852677309 +0 -0
  49. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.7.1/1024065805990144819 +0 -0
  50. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.7.1/285614542852677309 +0 -0
  51. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.7.3/16061516852537040135 +0 -0
  52. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.8.4/16354268377385700367 +0 -0
  53. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.9.10/12813592349865671909 +0 -0
  54. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.9.10/923908772239632759 +0 -0
  55. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.9.3/13948373885254993391 +0 -0
  56. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.9.9/12813592349865671909 +0 -0
  57. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/0.9.9/8843823720003377982 +0 -0
  58. {crackerjack-0.14.9 → crackerjack-0.15.0}/crackerjack/.ruff_cache/CACHEDIR.TAG +0 -0
  59. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/__init__.py +0 -0
  60. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/data/comments_sample.txt +0 -0
  61. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/data/docstrings_sample.txt +0 -0
  62. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/data/expected_comments_sample.txt +0 -0
  63. {crackerjack-0.14.9 → crackerjack-0.15.0}/tests/data/init.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crackerjack
3
- Version: 0.14.9
3
+ Version: 0.15.0
4
4
  Summary: Default template for PDM package
5
5
  Keywords: black,ruff,mypy,creosote,refurb
6
6
  Author-Email: lesleslie <les@wedgwoodwebworks.com>
@@ -125,15 +125,17 @@ Crackerjack automatically installs and manages these pre-commit hooks:
125
125
  Crackerjack projects adhere to these guidelines:
126
126
 
127
127
  - **Static Typing:** Use type hints consistently throughout your code.
128
+ - **Modern Type Hints:** Use the pipe operator (`|`) for union types (e.g., `Path | None` instead of `Optional[Path]`).
128
129
  - **Explicit Naming:** Choose clear, descriptive names for classes, functions, variables, and other identifiers.
129
130
  - **Markdown for Documentation:** Use Markdown (`.md`) for all documentation, READMEs, etc.
130
131
  - **Pathlib:** Use `pathlib.Path` for handling file and directory paths instead of `os.path`.
131
- - **Consistent Imports:** Use `import typing as t` for type hinting.
132
+ - **Consistent Imports:** Use `import typing as t` for type hinting and prefix all typing references with `t.`.
133
+ - **Protocol-Based Design:** Use `t.Protocol` for interface definitions instead of abstract base classes.
132
134
  - **Constants and Config:** Do not use all-caps for constants or configuration settings.
133
135
  - **Path Parameters:** Functions that handle file operations should accept `pathlib.Path` objects as parameters.
134
136
  - **Dependency Management:** Use PDM for dependency management, package building, and publishing.
135
137
  - **Testing:** Use pytest as your testing framework.
136
- - **Python Version:** Crackerjack projects support the latest Python versions.
138
+ - **Python Version:** Crackerjack projects target Python 3.13+ and use the latest language features.
137
139
  - **Clear Code:** Avoid overly complex code.
138
140
  - **Modular:** Functions should do one thing well.
139
141
 
@@ -155,10 +157,48 @@ Crackerjack projects adhere to these guidelines:
155
157
 
156
158
  ## Usage
157
159
 
160
+ ### Command Line
161
+
158
162
  Run Crackerjack from the root of your Python project using:
159
163
 
160
164
  python -m crackerjack
161
165
 
166
+ ### Programmatic API
167
+
168
+ You can also use Crackerjack programmatically in your Python code:
169
+
170
+ ```python
171
+ import typing as t
172
+ from pathlib import Path
173
+ from rich.console import Console
174
+ from crackerjack import create_crackerjack_runner
175
+
176
+ # Create a custom options object
177
+ class MyOptions:
178
+ def __init__(self):
179
+ self.commit = False
180
+ self.interactive = True
181
+ self.doc = False
182
+ self.no_config_updates = False
183
+ self.verbose = True
184
+ self.update_precommit = False
185
+ self.clean = True
186
+ self.test = True
187
+ self.publish = None
188
+ self.bump = "micro"
189
+ self.all = None
190
+
191
+ # Create a Crackerjack runner with custom settings
192
+ runner = create_crackerjack_runner(
193
+ console=Console(force_terminal=True),
194
+ pkg_path=Path.cwd(),
195
+ python_version="3.13"
196
+ )
197
+
198
+ # Run Crackerjack with your options
199
+ runner.process(MyOptions())
200
+ ```
201
+
162
202
 
163
203
  ### Command-Line Options
164
204
 
@@ -244,6 +284,17 @@ This ensures your code meets all quality standards before submission.
244
284
 
245
285
  This project is licensed under the terms of the BSD 3-Clause license.
246
286
 
287
+ ## Architecture
288
+
289
+ Crackerjack is designed with modern Python principles in mind:
290
+
291
+ - **Factory Pattern:** Uses a factory function (`create_crackerjack_runner`) to create instances with proper dependency injection
292
+ - **Protocol-Based Design:** Defines clear interfaces using `t.Protocol` for better flexibility and testability
293
+ - **Dependency Injection:** Components can be easily replaced with custom implementations
294
+ - **Separation of Concerns:** CLI interface is separate from core logic
295
+ - **Type Safety:** Comprehensive type hints throughout the codebase
296
+ - **Testability:** Designed to be easily testable with mock objects
297
+
247
298
  ## Acknowledgments
248
299
 
249
300
  - **PDM:** For excellent dependency and virtual environment management.
@@ -251,14 +302,14 @@ This project is licensed under the terms of the BSD 3-Clause license.
251
302
  - **pre-commit:** For the robust hook management system.
252
303
  - **pytest:** For the flexible and powerful testing framework.
253
304
  - **uv:** For greatly improving PDM speeds.
254
- - **bandit:** For finding security vulnerabilities.
255
- - **vulture:** for dead code detection.
256
- - **creosote:** For unused dependency detection.
257
- - **flynt:** For f-string conversion.
258
- - **codespell:** For spelling correction.
259
- - **autotyping:** For automatically adding type hints.
260
- - **refurb:** For code improvement suggestions.
261
- - **pyright:** For static type checking.
262
- - **Typer:** For the creation of the CLI.
305
+ - **bandit:** For finding security vulnerabilities.
306
+ - **vulture:** For dead code detection.
307
+ - **creosote:** For unused dependency detection.
308
+ - **flynt:** For f-string conversion.
309
+ - **codespell:** For spelling correction.
310
+ - **autotyping:** For automatically adding type hints.
311
+ - **refurb:** For code improvement suggestions.
312
+ - **pyright:** For static type checking.
313
+ - **Typer:** For the creation of the CLI.
263
314
 
264
315
  ---
@@ -86,15 +86,17 @@ Crackerjack automatically installs and manages these pre-commit hooks:
86
86
  Crackerjack projects adhere to these guidelines:
87
87
 
88
88
  - **Static Typing:** Use type hints consistently throughout your code.
89
+ - **Modern Type Hints:** Use the pipe operator (`|`) for union types (e.g., `Path | None` instead of `Optional[Path]`).
89
90
  - **Explicit Naming:** Choose clear, descriptive names for classes, functions, variables, and other identifiers.
90
91
  - **Markdown for Documentation:** Use Markdown (`.md`) for all documentation, READMEs, etc.
91
92
  - **Pathlib:** Use `pathlib.Path` for handling file and directory paths instead of `os.path`.
92
- - **Consistent Imports:** Use `import typing as t` for type hinting.
93
+ - **Consistent Imports:** Use `import typing as t` for type hinting and prefix all typing references with `t.`.
94
+ - **Protocol-Based Design:** Use `t.Protocol` for interface definitions instead of abstract base classes.
93
95
  - **Constants and Config:** Do not use all-caps for constants or configuration settings.
94
96
  - **Path Parameters:** Functions that handle file operations should accept `pathlib.Path` objects as parameters.
95
97
  - **Dependency Management:** Use PDM for dependency management, package building, and publishing.
96
98
  - **Testing:** Use pytest as your testing framework.
97
- - **Python Version:** Crackerjack projects support the latest Python versions.
99
+ - **Python Version:** Crackerjack projects target Python 3.13+ and use the latest language features.
98
100
  - **Clear Code:** Avoid overly complex code.
99
101
  - **Modular:** Functions should do one thing well.
100
102
 
@@ -116,10 +118,48 @@ Crackerjack projects adhere to these guidelines:
116
118
 
117
119
  ## Usage
118
120
 
121
+ ### Command Line
122
+
119
123
  Run Crackerjack from the root of your Python project using:
120
124
 
121
125
  python -m crackerjack
122
126
 
127
+ ### Programmatic API
128
+
129
+ You can also use Crackerjack programmatically in your Python code:
130
+
131
+ ```python
132
+ import typing as t
133
+ from pathlib import Path
134
+ from rich.console import Console
135
+ from crackerjack import create_crackerjack_runner
136
+
137
+ # Create a custom options object
138
+ class MyOptions:
139
+ def __init__(self):
140
+ self.commit = False
141
+ self.interactive = True
142
+ self.doc = False
143
+ self.no_config_updates = False
144
+ self.verbose = True
145
+ self.update_precommit = False
146
+ self.clean = True
147
+ self.test = True
148
+ self.publish = None
149
+ self.bump = "micro"
150
+ self.all = None
151
+
152
+ # Create a Crackerjack runner with custom settings
153
+ runner = create_crackerjack_runner(
154
+ console=Console(force_terminal=True),
155
+ pkg_path=Path.cwd(),
156
+ python_version="3.13"
157
+ )
158
+
159
+ # Run Crackerjack with your options
160
+ runner.process(MyOptions())
161
+ ```
162
+
123
163
 
124
164
  ### Command-Line Options
125
165
 
@@ -205,6 +245,17 @@ This ensures your code meets all quality standards before submission.
205
245
 
206
246
  This project is licensed under the terms of the BSD 3-Clause license.
207
247
 
248
+ ## Architecture
249
+
250
+ Crackerjack is designed with modern Python principles in mind:
251
+
252
+ - **Factory Pattern:** Uses a factory function (`create_crackerjack_runner`) to create instances with proper dependency injection
253
+ - **Protocol-Based Design:** Defines clear interfaces using `t.Protocol` for better flexibility and testability
254
+ - **Dependency Injection:** Components can be easily replaced with custom implementations
255
+ - **Separation of Concerns:** CLI interface is separate from core logic
256
+ - **Type Safety:** Comprehensive type hints throughout the codebase
257
+ - **Testability:** Designed to be easily testable with mock objects
258
+
208
259
  ## Acknowledgments
209
260
 
210
261
  - **PDM:** For excellent dependency and virtual environment management.
@@ -212,14 +263,14 @@ This project is licensed under the terms of the BSD 3-Clause license.
212
263
  - **pre-commit:** For the robust hook management system.
213
264
  - **pytest:** For the flexible and powerful testing framework.
214
265
  - **uv:** For greatly improving PDM speeds.
215
- - **bandit:** For finding security vulnerabilities.
216
- - **vulture:** for dead code detection.
217
- - **creosote:** For unused dependency detection.
218
- - **flynt:** For f-string conversion.
219
- - **codespell:** For spelling correction.
220
- - **autotyping:** For automatically adding type hints.
221
- - **refurb:** For code improvement suggestions.
222
- - **pyright:** For static type checking.
223
- - **Typer:** For the creation of the CLI.
266
+ - **bandit:** For finding security vulnerabilities.
267
+ - **vulture:** For dead code detection.
268
+ - **creosote:** For unused dependency detection.
269
+ - **flynt:** For f-string conversion.
270
+ - **codespell:** For spelling correction.
271
+ - **autotyping:** For automatically adding type hints.
272
+ - **refurb:** For code improvement suggestions.
273
+ - **pyright:** For static type checking.
274
+ - **Typer:** For the creation of the CLI.
224
275
 
225
276
  ---
@@ -0,0 +1,5 @@
1
+ import typing as t
2
+
3
+ from .crackerjack import Crackerjack, create_crackerjack_runner
4
+
5
+ __all__: t.Sequence[str] = ["create_crackerjack_runner", "Crackerjack"]
@@ -1,10 +1,9 @@
1
- import typing as t
2
1
  from enum import Enum
3
2
 
4
3
  import typer
5
4
  from pydantic import BaseModel, field_validator
6
5
  from rich.console import Console
7
- from crackerjack import crackerjack_it
6
+ from crackerjack import create_crackerjack_runner
8
7
 
9
8
  console = Console(force_terminal=True)
10
9
  app = typer.Typer(
@@ -26,17 +25,17 @@ class Options(BaseModel):
26
25
  interactive: bool = False
27
26
  doc: bool = False
28
27
  no_config_updates: bool = False
29
- publish: t.Optional[BumpOption] = None
30
- bump: t.Optional[BumpOption] = None
28
+ publish: BumpOption | None = None
29
+ bump: BumpOption | None = None
31
30
  verbose: bool = False
32
31
  update_precommit: bool = False
33
32
  clean: bool = False
34
33
  test: bool = False
35
- all: t.Optional[BumpOption] = None
34
+ all: BumpOption | None = None
36
35
 
37
36
  @classmethod
38
37
  @field_validator("publish", "bump", mode="before")
39
- def validate_bump_options(cls, value: t.Optional[str]) -> t.Optional[BumpOption]:
38
+ def validate_bump_options(cls, value: str | None) -> BumpOption | None:
40
39
  if value is None:
41
40
  return None
42
41
  try:
@@ -92,10 +91,6 @@ cli_options = {
92
91
  }
93
92
 
94
93
 
95
- def create_options(**kwargs: t.Any) -> Options:
96
- return Options(**kwargs)
97
-
98
-
99
94
  @app.command()
100
95
  def main(
101
96
  commit: bool = cli_options["commit"],
@@ -104,13 +99,13 @@ def main(
104
99
  no_config_updates: bool = cli_options["no_config_updates"],
105
100
  update_precommit: bool = cli_options["update_precommit"],
106
101
  verbose: bool = cli_options["verbose"],
107
- publish: t.Optional[BumpOption] = cli_options["publish"],
108
- all: t.Optional[BumpOption] = cli_options["all"],
109
- bump: t.Optional[BumpOption] = cli_options["bump"],
102
+ publish: BumpOption | None = cli_options["publish"],
103
+ all: BumpOption | None = cli_options["all"],
104
+ bump: BumpOption | None = cli_options["bump"],
110
105
  clean: bool = cli_options["clean"],
111
106
  test: bool = cli_options["test"],
112
107
  ) -> None:
113
- options = create_options(
108
+ options = Options(
114
109
  commit=commit,
115
110
  interactive=interactive,
116
111
  doc=doc,
@@ -123,7 +118,9 @@ def main(
123
118
  test=test,
124
119
  all=all,
125
120
  )
126
- crackerjack_it(options)
121
+
122
+ runner = create_crackerjack_runner(console=console)
123
+ runner.process(options)
127
124
 
128
125
 
129
126
  if __name__ == "__main__":
@@ -20,6 +20,28 @@ interactive_hooks = ("refurb", "bandit", "pyright")
20
20
  default_python_version = "3.13"
21
21
 
22
22
 
23
+ @t.runtime_checkable
24
+ class CommandRunner(t.Protocol):
25
+ def execute_command(
26
+ self, cmd: list[str], **kwargs: t.Any
27
+ ) -> subprocess.CompletedProcess[str]: ...
28
+
29
+
30
+ @t.runtime_checkable
31
+ class OptionsProtocol(t.Protocol):
32
+ commit: bool
33
+ interactive: bool
34
+ doc: bool
35
+ no_config_updates: bool
36
+ verbose: bool
37
+ update_precommit: bool
38
+ clean: bool
39
+ test: bool
40
+ publish: t.Any | None
41
+ bump: t.Any | None
42
+ all: t.Any | None
43
+
44
+
23
45
  @dataclass
24
46
  class CodeCleaner:
25
47
  console: Console
@@ -430,7 +452,7 @@ class Crackerjack:
430
452
  self.project_manager.pkg_name = self.pkg_name
431
453
  self.project_manager.pkg_dir = self.pkg_dir
432
454
 
433
- def _update_project(self, options: t.Any) -> None:
455
+ def _update_project(self, options: OptionsProtocol) -> None:
434
456
  if not options.no_config_updates:
435
457
  self.project_manager.update_pkg_configs()
436
458
  result: CompletedProcess[str] = self.execute_command(
@@ -443,16 +465,16 @@ class Crackerjack:
443
465
  "\n\n❌ PDM installation failed. Is PDM is installed? Run `pipx install pdm` and try again.\n\n"
444
466
  )
445
467
 
446
- def _update_precommit(self, options: t.Any) -> None:
468
+ def _update_precommit(self, options: OptionsProtocol) -> None:
447
469
  if self.pkg_path.stem == "crackerjack" and options.update_precommit:
448
470
  self.execute_command(["pre-commit", "autoupdate"])
449
471
 
450
- def _run_interactive_hooks(self, options: t.Any) -> None:
472
+ def _run_interactive_hooks(self, options: OptionsProtocol) -> None:
451
473
  if options.interactive:
452
474
  for hook in interactive_hooks:
453
475
  self.project_manager.run_interactive(hook)
454
476
 
455
- def _clean_project(self, options: t.Any) -> None:
477
+ def _clean_project(self, options: OptionsProtocol) -> None:
456
478
  if options.clean:
457
479
  if self.pkg_dir:
458
480
  self.code_cleaner.clean_files(self.pkg_dir)
@@ -461,7 +483,7 @@ class Crackerjack:
461
483
  self.console.print("\nCleaning tests directory...\n")
462
484
  self.code_cleaner.clean_files(tests_dir)
463
485
 
464
- def _run_tests(self, options: t.Any) -> None:
486
+ def _run_tests(self, options: OptionsProtocol) -> None:
465
487
  if options.test:
466
488
  self.console.print("\n\nRunning tests...\n")
467
489
  test = ["pytest"]
@@ -477,13 +499,13 @@ class Crackerjack:
477
499
  raise SystemExit(1)
478
500
  self.console.print("\n\n✅ Tests passed successfully!\n")
479
501
 
480
- def _bump_version(self, options: t.Any) -> None:
502
+ def _bump_version(self, options: OptionsProtocol) -> None:
481
503
  for option in (options.publish, options.bump):
482
504
  if option:
483
505
  self.execute_command(["pdm", "bump", option])
484
506
  break
485
507
 
486
- def _publish_project(self, options: t.Any) -> None:
508
+ def _publish_project(self, options: OptionsProtocol) -> None:
487
509
  if options.publish:
488
510
  if platform.system() == "Darwin":
489
511
  authorize = self.execute_command(
@@ -504,7 +526,7 @@ class Crackerjack:
504
526
  raise SystemExit(1)
505
527
  self.execute_command(["pdm", "publish", "--no-build"])
506
528
 
507
- def _commit_and_push(self, options: t.Any) -> None:
529
+ def _commit_and_push(self, options: OptionsProtocol) -> None:
508
530
  if options.commit:
509
531
  commit_msg = input("\nCommit message: ")
510
532
  self.execute_command(
@@ -520,7 +542,7 @@ class Crackerjack:
520
542
  return CompletedProcess(cmd, 0, "", "")
521
543
  return execute(cmd, **kwargs)
522
544
 
523
- def process(self, options: t.Any) -> None:
545
+ def process(self, options: OptionsProtocol) -> None:
524
546
  if options.all:
525
547
  options.clean = True
526
548
  options.test = True
@@ -536,7 +558,20 @@ class Crackerjack:
536
558
  self._bump_version(options)
537
559
  self._publish_project(options)
538
560
  self._commit_and_push(options)
539
- self.console.print("\nCrackerjack complete!\n")
540
-
541
-
542
- crackerjack_it = Crackerjack().process
561
+ self.console.print("\n🍺 Crackerjack complete!\n")
562
+
563
+
564
+ def create_crackerjack_runner(
565
+ console: Console | None = None,
566
+ our_path: Path | None = None,
567
+ pkg_path: Path | None = None,
568
+ python_version: str = default_python_version,
569
+ dry_run: bool = False,
570
+ ) -> Crackerjack:
571
+ return Crackerjack(
572
+ console=console or Console(force_terminal=True),
573
+ our_path=our_path or Path(__file__).parent,
574
+ pkg_path=pkg_path or Path.cwd(),
575
+ python_version=python_version,
576
+ dry_run=dry_run,
577
+ )
@@ -149,7 +149,7 @@ pythonPlatform = "Darwin"
149
149
 
150
150
  [project]
151
151
  name = "crackerjack"
152
- version = "0.14.8"
152
+ version = "0.14.9"
153
153
  description = "Default template for PDM package"
154
154
  requires-python = ">=3.13"
155
155
  readme = "README.md"
@@ -168,7 +168,7 @@ pythonPlatform = "Darwin"
168
168
 
169
169
  [project]
170
170
  name = "crackerjack"
171
- version = "0.14.9"
171
+ version = "0.15.0"
172
172
  description = "Default template for PDM package"
173
173
  requires-python = ">=3.13"
174
174
  readme = "README.md"
@@ -311,7 +311,7 @@ class TestCrackerjackProcess:
311
311
  mock_tests.assert_called_once()
312
312
  mock_publish.assert_called_once()
313
313
  mock_commit.assert_called_once()
314
- mock_console_print.assert_any_call("\nCrackerjack complete!\n")
314
+ mock_console_print.assert_any_call("\n🍺 Crackerjack complete!\n")
315
315
 
316
316
  def test_process_with_all_option_sets_flags(
317
317
  self,
@@ -0,0 +1,126 @@
1
+ import tempfile
2
+ import typing as t
3
+ from pathlib import Path
4
+ from unittest.mock import MagicMock, patch
5
+
6
+ import pytest
7
+ from rich.console import Console
8
+ from crackerjack import create_crackerjack_runner
9
+ from crackerjack.crackerjack import Crackerjack
10
+
11
+
12
+ class MockOptions:
13
+ def __init__(self, **kwargs: t.Any) -> None:
14
+ self.commit = kwargs.get("commit", False)
15
+ self.interactive = kwargs.get("interactive", False)
16
+ self.doc = kwargs.get("doc", False)
17
+ self.no_config_updates = kwargs.get("no_config_updates", False)
18
+ self.verbose = kwargs.get("verbose", False)
19
+ self.update_precommit = kwargs.get("update_precommit", False)
20
+ self.clean = kwargs.get("clean", False)
21
+ self.test = kwargs.get("test", False)
22
+ self.publish = kwargs.get("publish")
23
+ self.bump = kwargs.get("bump")
24
+ self.all = kwargs.get("all")
25
+
26
+
27
+ def test_create_crackerjack_runner() -> None:
28
+ console = Console(force_terminal=False)
29
+ runner = create_crackerjack_runner(console=console)
30
+
31
+ assert isinstance(runner, Crackerjack)
32
+ assert runner.console == console
33
+ assert runner.our_path == Path(__file__).parent.parent / "crackerjack"
34
+ assert runner.pkg_path == Path.cwd()
35
+ assert not runner.dry_run
36
+
37
+
38
+ @pytest.fixture
39
+ def mock_crackerjack():
40
+ with tempfile.TemporaryDirectory() as tmp_dir:
41
+ tmp_path = Path(tmp_dir)
42
+ console = MagicMock(spec=Console)
43
+
44
+ with (
45
+ patch("crackerjack.crackerjack.CodeCleaner") as mock_cleaner,
46
+ patch("crackerjack.crackerjack.ConfigManager") as mock_config,
47
+ patch("crackerjack.crackerjack.ProjectManager") as mock_project,
48
+ ):
49
+ mock_cleaner_instance = mock_cleaner.return_value
50
+ mock_config_instance = mock_config.return_value
51
+ mock_project_instance = mock_project.return_value
52
+
53
+ crackerjack = Crackerjack(
54
+ our_path=tmp_path,
55
+ pkg_path=tmp_path,
56
+ console=console,
57
+ code_cleaner=mock_cleaner_instance,
58
+ config_manager=mock_config_instance,
59
+ project_manager=mock_project_instance,
60
+ )
61
+
62
+ yield (
63
+ crackerjack,
64
+ {
65
+ "console": console,
66
+ "code_cleaner": mock_cleaner_instance,
67
+ "config_manager": mock_config_instance,
68
+ "project_manager": mock_project_instance,
69
+ },
70
+ )
71
+
72
+
73
+ def test_process_with_all_option(
74
+ mock_crackerjack: tuple[Crackerjack, dict[str, MagicMock]],
75
+ ) -> None:
76
+ crackerjack, mocks = mock_crackerjack
77
+
78
+ options = MockOptions(all="minor")
79
+
80
+ crackerjack.execute_command = MagicMock(return_value=MagicMock(returncode=0))
81
+
82
+ with patch("builtins.input", return_value="Test commit message"):
83
+ crackerjack.process(options)
84
+
85
+ assert options.clean is True
86
+ assert options.test is True
87
+ assert options.publish == "minor"
88
+ assert options.commit is True
89
+
90
+ mocks["project_manager"].run_pre_commit.assert_called_once()
91
+
92
+
93
+ def test_process_with_clean_option(
94
+ mock_crackerjack: tuple[Crackerjack, dict[str, MagicMock]],
95
+ ) -> None:
96
+ crackerjack, mocks = mock_crackerjack
97
+
98
+ options = MockOptions(clean=True)
99
+
100
+ crackerjack.pkg_dir = crackerjack.pkg_path / "test_pkg"
101
+
102
+ crackerjack.execute_command = MagicMock(return_value=MagicMock(returncode=0))
103
+
104
+ with patch("builtins.input", return_value="Test commit message"):
105
+ crackerjack.process(options)
106
+
107
+ mocks["code_cleaner"].clean_files.assert_called_with(crackerjack.pkg_dir)
108
+
109
+
110
+ def test_process_with_test_option(
111
+ mock_crackerjack: tuple[Crackerjack, dict[str, MagicMock]],
112
+ ) -> None:
113
+ crackerjack, _ = mock_crackerjack
114
+
115
+ options = MockOptions(test=True)
116
+
117
+ crackerjack.execute_command = MagicMock(
118
+ return_value=MagicMock(returncode=0, stdout="All tests passed", stderr="")
119
+ )
120
+
121
+ with patch("builtins.input", return_value="Test commit message"):
122
+ crackerjack.process(options)
123
+
124
+ crackerjack.execute_command.assert_any_call(
125
+ ["pytest"], capture_output=True, text=True
126
+ )
@@ -3,13 +3,16 @@ from unittest.mock import MagicMock, patch
3
3
 
4
4
  import pytest
5
5
  from typer.testing import CliRunner
6
- from crackerjack.__main__ import BumpOption, Options, app, create_options
6
+ from crackerjack.__main__ import BumpOption, Options, app
7
7
 
8
8
 
9
9
  @pytest.fixture
10
10
  def mock_crackerjack_process() -> t.Generator[MagicMock, None, None]:
11
- with patch("crackerjack.__main__.crackerjack_it") as mock_process:
12
- yield mock_process
11
+ mock_runner = MagicMock()
12
+ mock_create = MagicMock(return_value=mock_runner)
13
+
14
+ with patch("crackerjack.__main__.create_crackerjack_runner", mock_create):
15
+ yield mock_runner
13
16
 
14
17
 
15
18
  @pytest.fixture
@@ -20,8 +23,8 @@ def runner() -> CliRunner:
20
23
  def test_no_options(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
21
24
  result = runner.invoke(app)
22
25
  assert result.exit_code == 0
23
- mock_crackerjack_process.assert_called_once()
24
- options = mock_crackerjack_process.call_args[0][0]
26
+ mock_crackerjack_process.process.assert_called_once()
27
+ options = mock_crackerjack_process.process.call_args[0][0]
25
28
  assert isinstance(options, Options)
26
29
  assert not options.commit
27
30
  assert not options.interactive
@@ -38,13 +41,13 @@ def test_no_options(runner: CliRunner, mock_crackerjack_process: MagicMock) -> N
38
41
  def test_commit_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
39
42
  result = runner.invoke(app, ["-c"])
40
43
  assert result.exit_code == 0
41
- mock_crackerjack_process.assert_called_once()
42
- options = mock_crackerjack_process.call_args[0][0]
44
+ mock_crackerjack_process.process.assert_called_once()
45
+ options = mock_crackerjack_process.process.call_args[0][0]
43
46
  assert options.commit
44
- mock_crackerjack_process.reset_mock()
47
+ mock_crackerjack_process.process.reset_mock()
45
48
  result = runner.invoke(app, ["--commit"])
46
49
  assert result.exit_code == 0
47
- options = mock_crackerjack_process.call_args[0][0]
50
+ options = mock_crackerjack_process.process.call_args[0][0]
48
51
  assert options.commit
49
52
 
50
53
 
@@ -53,26 +56,26 @@ def test_interactive_option(
53
56
  ) -> None:
54
57
  result = runner.invoke(app, ["-i"])
55
58
  assert result.exit_code == 0
56
- mock_crackerjack_process.assert_called_once()
57
- options = mock_crackerjack_process.call_args[0][0]
59
+ mock_crackerjack_process.process.assert_called_once()
60
+ options = mock_crackerjack_process.process.call_args[0][0]
58
61
  assert options.interactive
59
- mock_crackerjack_process.reset_mock()
62
+ mock_crackerjack_process.process.reset_mock()
60
63
  result = runner.invoke(app, ["--interactive"])
61
64
  assert result.exit_code == 0
62
- options = mock_crackerjack_process.call_args[0][0]
65
+ options = mock_crackerjack_process.process.call_args[0][0]
63
66
  assert options.interactive
64
67
 
65
68
 
66
69
  def test_doc_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
67
70
  result = runner.invoke(app, ["-d"])
68
71
  assert result.exit_code == 0
69
- mock_crackerjack_process.assert_called_once()
70
- options = mock_crackerjack_process.call_args[0][0]
72
+ mock_crackerjack_process.process.assert_called_once()
73
+ options = mock_crackerjack_process.process.call_args[0][0]
71
74
  assert options.doc
72
- mock_crackerjack_process.reset_mock()
75
+ mock_crackerjack_process.process.reset_mock()
73
76
  result = runner.invoke(app, ["--doc"])
74
77
  assert result.exit_code == 0
75
- options = mock_crackerjack_process.call_args[0][0]
78
+ options = mock_crackerjack_process.process.call_args[0][0]
76
79
  assert options.doc
77
80
 
78
81
 
@@ -81,85 +84,85 @@ def test_update_precommit_option(
81
84
  ) -> None:
82
85
  result = runner.invoke(app, ["-u"])
83
86
  assert result.exit_code == 0
84
- mock_crackerjack_process.assert_called_once()
85
- options = mock_crackerjack_process.call_args[0][0]
87
+ mock_crackerjack_process.process.assert_called_once()
88
+ options = mock_crackerjack_process.process.call_args[0][0]
86
89
  assert options.update_precommit
87
- mock_crackerjack_process.reset_mock()
90
+ mock_crackerjack_process.process.reset_mock()
88
91
  result = runner.invoke(app, ["--update-precommit"])
89
92
  assert result.exit_code == 0
90
- options = mock_crackerjack_process.call_args[0][0]
93
+ options = mock_crackerjack_process.process.call_args[0][0]
91
94
  assert options.update_precommit
92
95
 
93
96
 
94
97
  def test_verbose_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
95
98
  result = runner.invoke(app, ["-v"])
96
99
  assert result.exit_code == 0
97
- mock_crackerjack_process.assert_called_once()
98
- options = mock_crackerjack_process.call_args[0][0]
100
+ mock_crackerjack_process.process.assert_called_once()
101
+ options = mock_crackerjack_process.process.call_args[0][0]
99
102
  assert options.verbose
100
- mock_crackerjack_process.reset_mock()
103
+ mock_crackerjack_process.process.reset_mock()
101
104
  result = runner.invoke(app, ["--verbose"])
102
105
  assert result.exit_code == 0
103
- options = mock_crackerjack_process.call_args[0][0]
106
+ options = mock_crackerjack_process.process.call_args[0][0]
104
107
  assert options.verbose
105
108
 
106
109
 
107
110
  def test_publish_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
108
111
  result = runner.invoke(app, ["-p", "micro"])
109
112
  assert result.exit_code == 0
110
- mock_crackerjack_process.assert_called_once()
111
- options = mock_crackerjack_process.call_args[0][0]
113
+ mock_crackerjack_process.process.assert_called_once()
114
+ options = mock_crackerjack_process.process.call_args[0][0]
112
115
  assert options.publish == BumpOption.micro
113
- mock_crackerjack_process.reset_mock()
116
+ mock_crackerjack_process.process.reset_mock()
114
117
  result = runner.invoke(app, ["--publish", "minor"])
115
118
  assert result.exit_code == 0
116
- options = mock_crackerjack_process.call_args[0][0]
119
+ options = mock_crackerjack_process.process.call_args[0][0]
117
120
  assert options.publish == BumpOption.minor
118
- mock_crackerjack_process.reset_mock()
121
+ mock_crackerjack_process.process.reset_mock()
119
122
  result = runner.invoke(app, ["--publish", "major"])
120
123
  assert result.exit_code == 0
121
- options = mock_crackerjack_process.call_args[0][0]
124
+ options = mock_crackerjack_process.process.call_args[0][0]
122
125
  assert options.publish == BumpOption.major
123
- mock_crackerjack_process.reset_mock()
126
+ mock_crackerjack_process.process.reset_mock()
124
127
  result = runner.invoke(app, ["--publish", "MICRO"])
125
128
  assert result.exit_code == 0
126
- options = mock_crackerjack_process.call_args[0][0]
129
+ options = mock_crackerjack_process.process.call_args[0][0]
127
130
  assert options.publish == BumpOption.micro
128
131
 
129
132
 
130
133
  def test_bump_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
131
134
  result = runner.invoke(app, ["-b", "micro"])
132
135
  assert result.exit_code == 0
133
- mock_crackerjack_process.assert_called_once()
134
- options = mock_crackerjack_process.call_args[0][0]
136
+ mock_crackerjack_process.process.assert_called_once()
137
+ options = mock_crackerjack_process.process.call_args[0][0]
135
138
  assert options.bump == BumpOption.micro
136
- mock_crackerjack_process.reset_mock()
139
+ mock_crackerjack_process.process.reset_mock()
137
140
  result = runner.invoke(app, ["--bump", "minor"])
138
141
  assert result.exit_code == 0
139
- options = mock_crackerjack_process.call_args[0][0]
142
+ options = mock_crackerjack_process.process.call_args[0][0]
140
143
  assert options.bump == BumpOption.minor
141
- mock_crackerjack_process.reset_mock()
144
+ mock_crackerjack_process.process.reset_mock()
142
145
  result = runner.invoke(app, ["--bump", "major"])
143
146
  assert result.exit_code == 0
144
- options = mock_crackerjack_process.call_args[0][0]
147
+ options = mock_crackerjack_process.process.call_args[0][0]
145
148
  assert options.bump == BumpOption.major
146
- mock_crackerjack_process.reset_mock()
149
+ mock_crackerjack_process.process.reset_mock()
147
150
  result = runner.invoke(app, ["--bump", "MICRO"])
148
151
  assert result.exit_code == 0
149
- options = mock_crackerjack_process.call_args[0][0]
152
+ options = mock_crackerjack_process.process.call_args[0][0]
150
153
  assert options.bump == BumpOption.micro
151
154
 
152
155
 
153
156
  def test_clean_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
154
157
  result = runner.invoke(app, ["-x"])
155
158
  assert result.exit_code == 0
156
- mock_crackerjack_process.assert_called_once()
157
- options = mock_crackerjack_process.call_args[0][0]
159
+ mock_crackerjack_process.process.assert_called_once()
160
+ options = mock_crackerjack_process.process.call_args[0][0]
158
161
  assert options.clean
159
- mock_crackerjack_process.reset_mock()
162
+ mock_crackerjack_process.process.reset_mock()
160
163
  result = runner.invoke(app, ["--clean"])
161
164
  assert result.exit_code == 0
162
- options = mock_crackerjack_process.call_args[0][0]
165
+ options = mock_crackerjack_process.process.call_args[0][0]
163
166
  assert options.clean
164
167
 
165
168
 
@@ -168,26 +171,26 @@ def test_no_config_updates(
168
171
  ) -> None:
169
172
  result = runner.invoke(app, ["-n"])
170
173
  assert result.exit_code == 0
171
- mock_crackerjack_process.assert_called_once()
172
- options = mock_crackerjack_process.call_args[0][0]
174
+ mock_crackerjack_process.process.assert_called_once()
175
+ options = mock_crackerjack_process.process.call_args[0][0]
173
176
  assert options.no_config_updates
174
- mock_crackerjack_process.reset_mock()
177
+ mock_crackerjack_process.process.reset_mock()
175
178
  result = runner.invoke(app, ["--no-config-updates"])
176
179
  assert result.exit_code == 0
177
- options = mock_crackerjack_process.call_args[0][0]
180
+ options = mock_crackerjack_process.process.call_args[0][0]
178
181
  assert options.no_config_updates
179
182
 
180
183
 
181
184
  def test_test_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
182
185
  result = runner.invoke(app, ["-t"])
183
186
  assert result.exit_code == 0
184
- mock_crackerjack_process.assert_called_once()
185
- options = mock_crackerjack_process.call_args[0][0]
187
+ mock_crackerjack_process.process.assert_called_once()
188
+ options = mock_crackerjack_process.process.call_args[0][0]
186
189
  assert options.test
187
- mock_crackerjack_process.reset_mock()
190
+ mock_crackerjack_process.process.reset_mock()
188
191
  result = runner.invoke(app, ["--test"])
189
192
  assert result.exit_code == 0
190
- options = mock_crackerjack_process.call_args[0][0]
193
+ options = mock_crackerjack_process.process.call_args[0][0]
191
194
  assert options.test
192
195
 
193
196
 
@@ -196,8 +199,8 @@ def test_multiple_options(
196
199
  ) -> None:
197
200
  result = runner.invoke(app, ["-c", "-i", "-d", "-t", "-x"])
198
201
  assert result.exit_code == 0
199
- mock_crackerjack_process.assert_called_once()
200
- options = mock_crackerjack_process.call_args[0][0]
202
+ mock_crackerjack_process.process.assert_called_once()
203
+ options = mock_crackerjack_process.process.call_args[0][0]
201
204
  assert options.commit
202
205
  assert options.interactive
203
206
  assert options.doc
@@ -206,7 +209,7 @@ def test_multiple_options(
206
209
 
207
210
 
208
211
  def test_create_options() -> None:
209
- test_options = create_options(
212
+ test_options = Options(
210
213
  commit=True,
211
214
  interactive=True,
212
215
  doc=True,
@@ -237,7 +240,7 @@ def test_conflicting_options(
237
240
  ) -> None:
238
241
  result = runner.invoke(app, ["-p", "micro", "-b", "minor"])
239
242
  assert result.exit_code == 0
240
- options = mock_crackerjack_process.call_args[0][0]
243
+ options = mock_crackerjack_process.process.call_args[0][0]
241
244
  assert options.publish == BumpOption.micro
242
245
  assert options.bump == BumpOption.minor
243
246
 
@@ -245,23 +248,23 @@ def test_conflicting_options(
245
248
  def test_all_option(runner: CliRunner, mock_crackerjack_process: MagicMock) -> None:
246
249
  result = runner.invoke(app, ["-a", "micro"])
247
250
  assert result.exit_code == 0
248
- mock_crackerjack_process.assert_called_once()
249
- options = mock_crackerjack_process.call_args[0][0]
251
+ mock_crackerjack_process.process.assert_called_once()
252
+ options = mock_crackerjack_process.process.call_args[0][0]
250
253
  assert options.all == BumpOption.micro
251
- mock_crackerjack_process.reset_mock()
254
+ mock_crackerjack_process.process.reset_mock()
252
255
  result = runner.invoke(app, ["--all", "minor"])
253
256
  assert result.exit_code == 0
254
- options = mock_crackerjack_process.call_args[0][0]
257
+ options = mock_crackerjack_process.process.call_args[0][0]
255
258
  assert options.all == BumpOption.minor
256
- mock_crackerjack_process.reset_mock()
259
+ mock_crackerjack_process.process.reset_mock()
257
260
  result = runner.invoke(app, ["--all", "major"])
258
261
  assert result.exit_code == 0
259
- options = mock_crackerjack_process.call_args[0][0]
262
+ options = mock_crackerjack_process.process.call_args[0][0]
260
263
  assert options.all == BumpOption.major
261
- mock_crackerjack_process.reset_mock()
264
+ mock_crackerjack_process.process.reset_mock()
262
265
  result = runner.invoke(app, ["--all", "MICRO"])
263
266
  assert result.exit_code == 0
264
- options = mock_crackerjack_process.call_args[0][0]
267
+ options = mock_crackerjack_process.process.call_args[0][0]
265
268
  assert options.all == BumpOption.micro
266
269
 
267
270
 
@@ -270,8 +273,8 @@ def test_all_option_with_other_options(
270
273
  ) -> None:
271
274
  result = runner.invoke(app, ["-a", "micro", "-c", "-t"])
272
275
  assert result.exit_code == 0
273
- mock_crackerjack_process.assert_called_once()
274
- options = mock_crackerjack_process.call_args[0][0]
276
+ mock_crackerjack_process.process.assert_called_once()
277
+ options = mock_crackerjack_process.process.call_args[0][0]
275
278
  assert options.all == BumpOption.micro
276
279
  assert options.commit
277
280
  assert options.test
@@ -1,5 +0,0 @@
1
- from typing import Sequence
2
-
3
- from .crackerjack import Crackerjack, crackerjack_it
4
-
5
- __all__: Sequence[str] = ["crackerjack_it", "Crackerjack"]
File without changes