crackerjack 0.14.9__py3-none-any.whl → 0.15.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.
- crackerjack/.ruff_cache/0.11.2/4070660268492669020 +0 -0
- crackerjack/__init__.py +3 -3
- crackerjack/__main__.py +12 -15
- crackerjack/crackerjack.py +48 -13
- crackerjack/pyproject.toml +1 -1
- {crackerjack-0.14.9.dist-info → crackerjack-0.15.0.dist-info}/METADATA +63 -12
- {crackerjack-0.14.9.dist-info → crackerjack-0.15.0.dist-info}/RECORD +10 -10
- {crackerjack-0.14.9.dist-info → crackerjack-0.15.0.dist-info}/WHEEL +0 -0
- {crackerjack-0.14.9.dist-info → crackerjack-0.15.0.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.14.9.dist-info → crackerjack-0.15.0.dist-info}/licenses/LICENSE +0 -0
Binary file
|
crackerjack/__init__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
1
|
+
import typing as t
|
2
2
|
|
3
|
-
from .crackerjack import Crackerjack,
|
3
|
+
from .crackerjack import Crackerjack, create_crackerjack_runner
|
4
4
|
|
5
|
-
__all__: Sequence[str] = ["
|
5
|
+
__all__: t.Sequence[str] = ["create_crackerjack_runner", "Crackerjack"]
|
crackerjack/__main__.py
CHANGED
@@ -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
|
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:
|
30
|
-
bump:
|
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:
|
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:
|
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:
|
108
|
-
all:
|
109
|
-
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 =
|
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
|
-
|
121
|
+
|
122
|
+
runner = create_crackerjack_runner(console=console)
|
123
|
+
runner.process(options)
|
127
124
|
|
128
125
|
|
129
126
|
if __name__ == "__main__":
|
crackerjack/crackerjack.py
CHANGED
@@ -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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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("\
|
540
|
-
|
541
|
-
|
542
|
-
|
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
|
+
)
|
crackerjack/pyproject.toml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crackerjack
|
3
|
-
Version: 0.
|
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
|
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
|
-
-
|
255
|
-
-
|
256
|
-
-
|
257
|
-
-
|
258
|
-
-
|
259
|
-
-
|
260
|
-
-
|
261
|
-
-
|
262
|
-
-
|
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
|
---
|
@@ -1,7 +1,7 @@
|
|
1
|
-
crackerjack-0.
|
2
|
-
crackerjack-0.
|
3
|
-
crackerjack-0.
|
4
|
-
crackerjack-0.
|
1
|
+
crackerjack-0.15.0.dist-info/METADATA,sha256=iaO-taRUDnYZX96TflzDZiPWu-9VO-XVYl-Y8ZNdrx8,12863
|
2
|
+
crackerjack-0.15.0.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
|
3
|
+
crackerjack-0.15.0.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
4
|
+
crackerjack-0.15.0.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
|
5
5
|
crackerjack/.coverage,sha256=dLzPzp72qZEXohNfxnOAlRwvM9dqF06-HoFqfvXZd1U,53248
|
6
6
|
crackerjack/.gitignore,sha256=l8ErBAypC3rI6N9lhc7ZMdOw87t0Tz69ZW5C6uj15Wg,214
|
7
7
|
crackerjack/.libcst.codemod.yaml,sha256=a8DlErRAIPV1nE6QlyXPAzTOgkB24_spl2E9hphuf5s,772
|
@@ -19,7 +19,7 @@ crackerjack/.ruff_cache/0.1.4/10355199064880463147,sha256=kmqNg5WySQYPeAqa5elfaV
|
|
19
19
|
crackerjack/.ruff_cache/0.1.6/15140459877605758699,sha256=oQy5boAXeskdm5M0Abh_nyBtitWj5N5wtx_4gsDgu7c,248
|
20
20
|
crackerjack/.ruff_cache/0.1.7/1790508110482614856,sha256=De7Puq32XF0925xrGehWSKX6cw5Wi2bpt1cnqh__f54,248
|
21
21
|
crackerjack/.ruff_cache/0.1.9/17041001205004563469,sha256=tKP_k8HaHhQJyrHbDfJ93kM7vahjrU8cKQ1f_-OUzZY,248
|
22
|
-
crackerjack/.ruff_cache/0.11.2/4070660268492669020,sha256=
|
22
|
+
crackerjack/.ruff_cache/0.11.2/4070660268492669020,sha256=vqJ78zDU4OSZumr4xwG-k2cPXu_ATHqYmBc78aW33-o,224
|
23
23
|
crackerjack/.ruff_cache/0.2.0/10047773857155985907,sha256=j9LNa_RQ4Plor7go1uTYgz17cEENKvZQ-dP6b9MX0ik,248
|
24
24
|
crackerjack/.ruff_cache/0.2.1/8522267973936635051,sha256=u_aPBMibtAp_iYvLwR88GMAECMcIgHezxMyuapmU2P4,248
|
25
25
|
crackerjack/.ruff_cache/0.2.2/18053836298936336950,sha256=Xb_ebP0pVuUfSqPEZKlhQ70so_vqkEfMYpuHQ06iR5U,248
|
@@ -47,8 +47,8 @@ crackerjack/.ruff_cache/0.9.3/13948373885254993391,sha256=kGhtIkzPUtKAgvlKs3D8j4
|
|
47
47
|
crackerjack/.ruff_cache/0.9.9/12813592349865671909,sha256=tmr8_vhRD2OxsVuMfbJPdT9fDFX-d5tfC5U9jgziyho,224
|
48
48
|
crackerjack/.ruff_cache/0.9.9/8843823720003377982,sha256=e4ymkXfQsUg5e_mtO34xTsaTvs1uA3_fI216Qq9qCAM,136
|
49
49
|
crackerjack/.ruff_cache/CACHEDIR.TAG,sha256=WVMVbX4MVkpCclExbq8m-IcOZIOuIZf5FrYw5Pk-Ma4,43
|
50
|
-
crackerjack/__init__.py,sha256=
|
51
|
-
crackerjack/__main__.py,sha256=
|
52
|
-
crackerjack/crackerjack.py,sha256=
|
53
|
-
crackerjack/pyproject.toml,sha256=
|
54
|
-
crackerjack-0.
|
50
|
+
crackerjack/__init__.py,sha256=r9SuEjHUrW99hFWifRk4ofmYPSgf9rblcnzqhdV5bP0,157
|
51
|
+
crackerjack/__main__.py,sha256=iwoUyUB9j3e5lC5ViNAqW00eeoIx0xljNmWC04AiPaw,3707
|
52
|
+
crackerjack/crackerjack.py,sha256=alZ44ZldvqTpKo2RkAA0kq9RTueFeYeq__YbRlLN1Vg,22355
|
53
|
+
crackerjack/pyproject.toml,sha256=Q00BGPOeoESTrTbRFUFNXmoskntjP36eypSEDmYAMzk,4089
|
54
|
+
crackerjack-0.15.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|