Skip to content

Commit 1954742

Browse files
authored
Merge pull request #17
General Refactoring
2 parents 0d051e3 + 4935237 commit 1954742

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1639
-1399
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.pre-commit-config.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
exclude: "^{{cookiecutter\\.project_name}}/"
2+
repos:
3+
- repo: https://github.com/pre-commit/pre-commit-hooks
4+
rev: v4.1.0
5+
hooks:
6+
- id: check-yaml
7+
- id: end-of-file-fixer
8+
- id: trailing-whitespace
9+
- id: check-added-large-files
10+
- repo: https://github.com/pre-commit/mirrors-prettier
11+
rev: v2.6.0
12+
hooks:
13+
- id: prettier

README.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
A Python project template robust enough to follow up [cookiecutter-hypermodern-python]
44

55
# Caveat
6+
67
I really believe this idea has a lot of good ideas and best practices, however, creating it is a ton of work.
78

89
There is definitely a lot left to do before this project is truly a daily driver, but I think there are just a few more pieces missing from this being at least useful in many cases.
910

1011
If you have any interest in this project, please don't hesitate to reach out!
1112
Any advice, support, PR's, etc. are welcome and would be greatly appreciated.
1213

13-
1414
# Why does this project exist?
15+
1516
Unfortunately, the [Hypermodern Python Cookiecutter] is no longer maintained nor modern.
1617
While it will always have a place in my heart, there have been far too many improvements in Python tooling to keep using it as is.
1718

@@ -22,15 +23,17 @@ The [Hypermodern Python Cookiecutter] remains as a fantastic sendoff point for d
2223
a handful of issues with it that prevented it from being able to adapt to new Python developments over the years.
2324

2425
# Okay, so what's different this time?
26+
2527
The [Robust Python Cookiecutter] exists to solve a few main concerns
28+
2629
- [Template Update Propagation](#template-update-propagation)
2730
- [Project Domain Expansion](#project-domain-expansion)
2831
- [Documenting Tooling Decisions](#documenting-tooling-decisions)
2932
- [CI/CD Vendor Lock](#cicd-vendor-lock)
3033
- [Project Neglect](#project-neglect)
3134

32-
3335
## Template Update Propagation
36+
3437
One of the main issues I encountered with [my personal fork] of the [Hypermodern Python Cookiecutter] was that any change
3538
I made to my repos would mean a later conflict if I tried to rerun [cookiecutter] to sync a change from a different project.
3639

@@ -40,8 +43,8 @@ the [Robust Python Cookiecutter] may have added.
4043
Additionally, extra care is put in to use tooling specific config files whenever possible to help reduce merge conflicts occurring
4144
in the pyproject.toml.
4245

43-
4446
## Project Domain Expansion
47+
4548
Now, I'm not one to advocate for mixing languages in a project. However, there is a unique case that has arisen with the creation of [maturin].
4649

4750
There are a plethora of great projects such as [ruff], [uv], [polars], [just], etc. all making use of [maturin] to get the performance improvements of [rust] while
@@ -51,27 +54,30 @@ Now, this definitely is not required by any means to make a good Python package,
5154
to Python's ecosystem overall.
5255

5356
That being said, it's generally good practice to avoid the complexity of this dual language system unless you actually need the performance bump for your use case. However knowing ahead of time if performance
54-
will be an issue is rather tricky, and a much easier route is to just prepare as though you *might* swap to it some day.
57+
will be an issue is rather tricky, and a much easier route is to just prepare as though you _might_ swap to it some day.
5558

5659
The [Robust Python Cookiecutter] includes a `include_rust_extensions` flag that not only toggles [maturin] vs a traditional Python package,
5760
but that can be used in combination with [cruft] to swap to [maturin] at any time with just about no risk to CI/CD / etc.
5861

5962
Additionally, the [Robust Python Cookiecutter] is designed with both normal and [monorepos] in mind. So whether you need to just add
6063
a quick [rust] module for performance or you are trying to publish a series of crates and packages, either case will be handled using a setup inspired by [polars].
6164

62-
6365
## Documenting Tooling Decisions
66+
6467
One of the really stand out features of the [Hypermodern Python Cookiecutter] was its incredibly detailed documentation.
65-
It did a pretty great job of describing the tooling to use, but there was a distinct lack of ***why*** these decisions were made.
68+
It did a pretty great job of describing the tooling to use, but there was a distinct lack of **_why_** these decisions were made.
6669

6770
It may seem like a small detail, but detailing why a decision was made has an incredibly important effect on the maintainablity of the template.
71+
6872
#### **It allows maintainers to check if a decision should change in one click.**
73+
6974
Rather than having to go through a mini crusade to determine whether we use [poetry] or [uv], we can just point to the
7075
[existing reasoning](https://cookiecutter-robust-python.readthedocs.io/en/latest/topics/02_dependency_management.md#option-2--term--poetry) to see if it still is true or not.
7176

7277
Overall, it's rather rare that people debate over tooling for no reason. Most things have merit in some cases, and a large goal of this template is identifying the tools that have the most merit in almost all cases.
7378

7479
## CI/CD Vendor Lock
80+
7581
Now don't get me wrong, I love [github-actions] and do pretty much everything in my power to avoid [bitbucket-pipelines].
7682
However, not all jobs have the luxury of GitHub, and I would love to be able to just use the same template for both my personal and professional projects.
7783

@@ -84,8 +90,8 @@ The local [noxfile] is designed to match up directly with the CI/CD each step of
8490
The [Hypermodern Python Cookiecutter] did this where it could afford to also, however the lack of [uv] meant it would significantly increase CI/CD times if done everywhere.
8591
Thankfully now we can spin up a venv with a tiny fraction of the overhead that used to exist.
8692

87-
8893
## Project Neglect
94+
8995
This is most certainly not a knock against claudio. The work they did on [cookiecutter-hypermodern-python] laid the way for countless other devs to start
9096
implementing best practices in their python packages.
9197

@@ -100,16 +106,14 @@ of trusted individuals to ensure the project is taken care of.
100106
[cookiecutter-robust-python]: https://github.com/56kyle/cookiecutter-robust-python
101107
[cruft]: https://cruft.github.io/cruft/
102108
[github-actions]: https://docs.github.com/en/actions
103-
[Hypermodern Python Cookiecutter]: https://github.com/cjolowicz/cookiecutter-hypermodern-python
109+
[hypermodern python cookiecutter]: https://github.com/cjolowicz/cookiecutter-hypermodern-python
104110
[just]: https://github.com/casey/just?tab=readme-ov-fil
105111
[maturin]: https://github.com/PyO3/maturin
106112
[noxfile]: https://github.com/56kyle/cookiecutter-robust-python/blob/main/%7B%7Bcookiecutter.project_name%7D%7D/noxfile.py
107113
[poetry]: https://python-poetry.org/docs/
108114
[polars]: https://github.com/pola-rs/polars
109-
[Robust Python Cookiecutter]: https://github.com/56kyle/cookiecutter-robust-python
115+
[robust python cookiecutter]: https://github.com/56kyle/cookiecutter-robust-python
110116
[ruff]: https://docs.astral.sh/ruff/
111117
[rust]: https://www.rust-lang.org/learn
112-
[Rye]: https://rye.astral.sh/
118+
[rye]: https://rye.astral.sh/
113119
[uv]: https://docs.astral.sh/uv/
114-
115-

docs/criteria.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,34 @@
22

33
Tooling choices in `cookiecutter-robust-python` are not arbitrary. Every significant tool or approach evaluated for inclusion was assessed based on a consistent set of criteria derived directly from the template's core philosophy ([Template Philosophy: The Zen of cookiecutter-robust-python](philosophy.md)).
44

5-
Understanding these criteria is key to understanding *why* the template uses the tools it does, and how to evaluate alternative tools or approaches as the ecosystem evolves.
5+
Understanding these criteria is key to understanding _why_ the template uses the tools it does, and how to evaluate alternative tools or approaches as the ecosystem evolves.
66

77
## Global Criteria
88

99
These criteria were applied broadly across most tool categories and workflow stages. They represent fundamental requirements or strong preferences for any tool adopted as a core part of the template's foundation:
1010

11-
* **PEP Compliance:** Adherence to relevant Python Enhancement Proposals (packaging - PEP 518, 621, 427, 660; typing - PEP 484, 526; style - PEP 8, PEP 257) and other established standards (e.g., TOML, YAML for configuration, standard report formats like JUnit XML, Cobertura XML). *Especially crucial for configuration formats and standard tool interaction methods*. This is a **non-negotiable requirement** where applicable and defined standards exist.
12-
* **OS Interoperability:** The tool itself, its method of installation, and its core execution logic (including environment management for task runners) must work reliably and consistently across standard development operating systems: Linux, macOS, and Windows. Complex OS-specific workarounds in standard workflows are strongly avoided. This is a **non-negotiable requirement** for the core developer experience and automated workflows.
13-
* **CLI Callability:** The tool must have a stable and predictable command-line interface that can be easily invoked and scripted by automation layers ([Task Automation (12)](topics/12_task-automation.md), [CI Orchestration (13)](topics/13_ci-orchestration.md), [CD Orchestration (14)](topics/14_cd-orchestration.md)).
14-
* **Developer Experience (DX):** How intuitive, straightforward, and efficient is the tool's usage for a developer? Does it streamline common tasks (e.g., adding deps, running checks)? Does it provide clear feedback?
15-
* **Performance:** Speed of execution for the task the tool performs. This is particularly important for automated steps that run frequently (editors, pre-commit, CI) or take significant time (dependency resolution, large test suites, complex builds). Faster automation directly supports the "Automated is better than manual" principle by reducing waiting time.
16-
* **Maintainability:** The tool should contribute to the long-term health of the project and the template. Factors include: ease of updating the tool, clarity of its configuration, potential for tool consolidation (reducing tool count), stability of its API/behavior, and ease of contributing to its development (community).
17-
* **Reproducibility:** Tools involved in dependency management ([Dependency Management (02)](topics/02_dependency-management.md)) and building ([Packaging Build (09)](topics/09_packaging-build.md), [Container Build (11)](topics/11_container-build.md)) must ensure that the same inputs consistently produce the same outputs across environments where feasible.
18-
* **Maturity & Stability:** How stable is the tool's public interface and behavior? How long has it been battle-tested in real-world projects? Tools marked as explicitly "experimental" are generally avoided for the template's core foundation unless their technical merits are overwhelmingly compelling and stable for the task *despite* the label.
19-
* **Community & Documentation:** An active development community, good community support (forums, Stack Overflow), and comprehensive, clear documentation are vital for troubleshooting and learning.
20-
* **Best Tool for the Job vs. Tooling Origin:** The primary goal is to select the tool that best meets *all other criteria* for its specific task, even if it means choosing a tool not implemented in Python itself (e.g., Rust-based). Technical merit and alignment with core requirements override the language of implementation.
11+
- **PEP Compliance:** Adherence to relevant Python Enhancement Proposals (packaging - PEP 518, 621, 427, 660; typing - PEP 484, 526; style - PEP 8, PEP 257) and other established standards (e.g., TOML, YAML for configuration, standard report formats like JUnit XML, Cobertura XML). _Especially crucial for configuration formats and standard tool interaction methods_. This is a **non-negotiable requirement** where applicable and defined standards exist.
12+
- **OS Interoperability:** The tool itself, its method of installation, and its core execution logic (including environment management for task runners) must work reliably and consistently across standard development operating systems: Linux, macOS, and Windows. Complex OS-specific workarounds in standard workflows are strongly avoided. This is a **non-negotiable requirement** for the core developer experience and automated workflows.
13+
- **CLI Callability:** The tool must have a stable and predictable command-line interface that can be easily invoked and scripted by automation layers ([Task Automation (12)](topics/12_task-automation.md), [CI Orchestration (13)](topics/13_ci-orchestration.md), [CD Orchestration (14)](topics/14_cd-orchestration.md)).
14+
- **Developer Experience (DX):** How intuitive, straightforward, and efficient is the tool's usage for a developer? Does it streamline common tasks (e.g., adding deps, running checks)? Does it provide clear feedback?
15+
- **Performance:** Speed of execution for the task the tool performs. This is particularly important for automated steps that run frequently (editors, pre-commit, CI) or take significant time (dependency resolution, large test suites, complex builds). Faster automation directly supports the "Automated is better than manual" principle by reducing waiting time.
16+
- **Maintainability:** The tool should contribute to the long-term health of the project and the template. Factors include: ease of updating the tool, clarity of its configuration, potential for tool consolidation (reducing tool count), stability of its API/behavior, and ease of contributing to its development (community).
17+
- **Reproducibility:** Tools involved in dependency management ([Dependency Management (02)](topics/02_dependency-management.md)) and building ([Packaging Build (09)](topics/09_packaging-build.md), [Container Build (11)](topics/11_container-build.md)) must ensure that the same inputs consistently produce the same outputs across environments where feasible.
18+
- **Maturity & Stability:** How stable is the tool's public interface and behavior? How long has it been battle-tested in real-world projects? Tools marked as explicitly "experimental" are generally avoided for the template's core foundation unless their technical merits are overwhelmingly compelling and stable for the task _despite_ the label.
19+
- **Community & Documentation:** An active development community, good community support (forums, Stack Overflow), and comprehensive, clear documentation are vital for troubleshooting and learning.
20+
- **Best Tool for the Job vs. Tooling Origin:** The primary goal is to select the tool that best meets _all other criteria_ for its specific task, even if it means choosing a tool not implemented in Python itself (e.g., Rust-based). Technical merit and alignment with core requirements override the language of implementation.
2121

2222
## Area-Specific Criteria
2323

2424
In addition to the global criteria, certain areas introduced specific criteria relevant to the task at hand. These are detailed within each topic's dedicated documentation page but include examples like:
2525

26-
* For [Dependency Management (02)](topics/02_dependency-management.md): Reliability of the dependency resolver on complex graphs, effectiveness of lock files.
27-
* For [Code Formatting (03)](topics/03_code-formatting.md): Opinionatedness of style, accuracy of style enforcement (vs. PEP 8 compatible).
28-
* For [Type Checking (05)](topics/05_type-checking.md): Strictness of type checking, support for standard type hinting PEPs, effectiveness with type stubs.
29-
* For [Packaging Build (09)](topics/09_packaging-build.md): Support for native code extensions and the complexity of cross-platform compilation.
30-
* For [Task Automation (12)](topics/12_task-automation.md): Effectiveness of task environment isolation.
31-
* For [Container Build (11)](topics/11_container-build.md): Support for container build best practices (multistage builds, non-root users).
32-
* For [CI Orchestration (13)](topics/13_ci-orchestration.md): Effectiveness of platform matrix testing features.
33-
* For [Pre-commit Hooks (18)](topics/18_pre-commit-hooks.md): Speed of execution relative to the commit process.
26+
- For [Dependency Management (02)](topics/02_dependency-management.md): Reliability of the dependency resolver on complex graphs, effectiveness of lock files.
27+
- For [Code Formatting (03)](topics/03_code-formatting.md): Opinionatedness of style, accuracy of style enforcement (vs. PEP 8 compatible).
28+
- For [Type Checking (05)](topics/05_type-checking.md): Strictness of type checking, support for standard type hinting PEPs, effectiveness with type stubs.
29+
- For [Packaging Build (09)](topics/09_packaging-build.md): Support for native code extensions and the complexity of cross-platform compilation.
30+
- For [Task Automation (12)](topics/12_task-automation.md): Effectiveness of task environment isolation.
31+
- For [Container Build (11)](topics/11_container-build.md): Support for container build best practices (multistage builds, non-root users).
32+
- For [CI Orchestration (13)](topics/13_ci-orchestration.md): Effectiveness of platform matrix testing features.
33+
- For [Pre-commit Hooks (18)](topics/18_pre-commit-hooks.md): Speed of execution relative to the commit process.
3434

3535
By evaluating all potential tools against these consistent criteria, we aim to demonstrate that the template's toolchain is not just a collection of popular tools, but a thoughtfully selected, integrated stack designed for building **robust and maintainable** Python projects.

0 commit comments

Comments
 (0)