|
1 | | -<div align="center"><a name="readme-top"></a> |
| 1 | +<div align="center" markdown> |
2 | 2 |
|
3 | | - |
| 3 | + |
| 4 | + |
| 5 | +**[Browse the template files »](https://github.com/liblaf/copier-python/tree/main/template)** |
4 | 6 |
|
5 | 7 | [](https://github.com/copier-org/copier) |
| 8 | +[](https://github.com/liblaf/copier-python/actions/workflows/mega-linter.yaml) |
| 9 | +[](https://github.com/liblaf/copier-python/actions/workflows/release-pr.yaml) |
| 10 | +[](https://github.com/liblaf/copier-python/actions/workflows/copier-update.yaml) |
6 | 11 |
|
7 | | -[Changelog](https://github.com/liblaf/copier-python/blob/main/CHANGELOG.md) · [Report Bug](https://github.com/liblaf/copier-python/issues) · [Request Feature](https://github.com/liblaf/copier-python/issues) |
| 12 | +[Changelog](https://github.com/liblaf/copier-python/blob/main/CHANGELOG.md) · [Template Files](https://github.com/liblaf/copier-python/tree/main/template) · [Report Bug](https://github.com/liblaf/copier-python/issues) · [Request Feature](https://github.com/liblaf/copier-python/issues) |
8 | 13 |
|
9 | | - |
| 14 | + |
10 | 15 |
|
11 | 16 | </div> |
12 | 17 |
|
13 | | -## ✨ Features |
14 | | - |
15 | | -- 🐍 Bootstraps a modern Python project on a typed `src/` layout. |
16 | | -- 🧱 Designed to layer on top of [`gh:liblaf/copier-shared`](https://github.com/liblaf/copier-shared) and [`gh:liblaf/copier-release`](https://github.com/liblaf/copier-release). |
17 | | -- ⚡ Uses `uv` for dependency management and `mise` for repeatable local tasks. |
18 | | -- ✅ Ships with `nox`, `pytest`, coverage, Ruff, import-linter, and shared repository defaults. |
19 | | -- 📚 Generates docs with Zensical, MkDocs Material, mkdocstrings, GitHub Pages, and Read the Docs. |
20 | | -- 🚀 Builds with Hatchling plus Hatch VCS and publishes to PyPI and GitHub Releases. |
21 | | -- 🧪 Includes benchmark workflow wiring with CodSpeed. |
| 18 | +## 🐍 What Is `copier-python`? |
22 | 19 |
|
23 | | -## 🧱 Template Stack |
| 20 | +`copier-python` is the Python layer in the `liblaf` Copier stack. It adds packaging, typed source layout, documentation, testing, benchmarking, and PyPI publishing on top of the shared repository and release foundations. |
24 | 21 |
|
25 | | -This template is the Python layer of a three-template setup: |
| 22 | +> [!IMPORTANT] |
| 23 | +> This template depends on [`gh:liblaf/copier-shared`](https://github.com/liblaf/copier-shared) and [`gh:liblaf/copier-release`](https://github.com/liblaf/copier-release). Apply the stack in that order: shared → release → python. |
26 | 24 |
|
27 | | -1. [`gh:liblaf/copier-shared`](https://github.com/liblaf/copier-shared) |
28 | | -2. [`gh:liblaf/copier-release`](https://github.com/liblaf/copier-release) |
29 | | -3. `gh:liblaf/copier-python` |
| 25 | +If you want the real source of truth for generated files, start in [`template/`](https://github.com/liblaf/copier-python/tree/main/template). This repository README documents the template itself; the generated project README comes from [`template/README.md.jinja`](https://github.com/liblaf/copier-python/blob/main/template/README.md.jinja). |
30 | 26 |
|
31 | | -Apply them in that order. `copier-python` expects the shared project metadata and release automation from the first two templates to already exist. |
| 27 | +## ✨ What You Get |
32 | 28 |
|
33 | | -## 🚀 Create a Project |
| 29 | +- 📦 A modern Python package layout under `src/`, including `py.typed`, version stubs, and lazy-loader-friendly package exports. |
| 30 | +- ⚙️ A `pyproject.toml` wired for PEP 621 metadata, `uv` dependency groups, Hatchling builds, and Hatch VCS versioning. |
| 31 | +- 🧪 A `noxfile.py` with multi-version test sessions, dependency resolution variants, and optional benchmark sessions. |
| 32 | +- 📚 Docs scaffolding with Zensical, MkDocs Material, mkdocstrings, GitHub-friendly Markdown, and Read the Docs configuration. |
| 33 | +- 🚀 Release automation that fits the rest of the `liblaf` Copier stack, including changelog generation, draft releases, and PyPI publishing through OIDC. |
| 34 | +- 🔁 Copier-friendly update paths so the generated repository can be refreshed later without redoing the whole setup by hand. |
34 | 35 |
|
35 | | -```bash |
36 | | -copier copy gh:liblaf/copier-shared . |
37 | | -copier copy gh:liblaf/copier-release . |
38 | | -copier copy gh:liblaf/copier-python . |
39 | | -``` |
| 36 | +## 🚀 Apply The Template |
40 | 37 |
|
41 | | -To refresh the Python layer later: |
| 38 | +After applying the shared and release templates, add the Python layer with: |
42 | 39 |
|
43 | 40 | ```bash |
44 | | -copier recopy --answers-file '.config/copier/.copier-answers.python.yaml' |
| 41 | +copier copy --trust gh:liblaf/copier-python . |
45 | 42 | ``` |
46 | 43 |
|
47 | | -The generated repository will also keep the answers files from the shared and release templates, so automated Copier update workflows can refresh the full stack. |
48 | | - |
49 | | -## 🧰 What You Get |
| 44 | +## 🔄 Update The Template |
50 | 45 |
|
51 | | -- `pyproject.toml` with PEP 621 metadata, dependency groups, Hatchling packaging, and Hatch VCS versioning. |
52 | | -- `noxfile.py` with reusable test sessions across declared Python versions plus tagged dependency-resolution variants. |
53 | | -- `.config/mise/conf.d/50-python.toml` with ready-to-run tasks such as `install`, `lint`, `docs:build`, `docs:serve`, `gen:init`, and `upgrade`. |
54 | | -- `zensical.toml`, `.readthedocs.yaml`, and Python-specific GitHub Actions workflows for docs, tests, benchmarks, and publishing. |
55 | | -- A typed package skeleton under `src/` with `py.typed`, version stubs, and lazy-loader friendly `__init__.py` generation from `__init__.pyi`. |
56 | | - |
57 | | -## ⌨️ Local Development |
58 | | - |
59 | | -After generating a project from this template, the usual workflow is: |
| 46 | +To refresh the Python layer in an existing repository: |
60 | 47 |
|
61 | 48 | ```bash |
62 | | -mise run install |
63 | | -mise run lint |
64 | | -nox |
65 | | -mise run docs:serve |
| 49 | +copier recopy --trust --answers-file '.config/copier/.copier-answers.python.yaml' |
66 | 50 | ``` |
67 | 51 |
|
68 | | -Useful extra commands: |
| 52 | +The generated repository usually keeps separate Copier answers files for each layer, so scheduled update workflows can refresh the whole stack over time. |
69 | 53 |
|
70 | | -- `mise run docs:build` to build the docs site locally. |
71 | | -- `mise run gen:init` to regenerate `__init__.py` files from `__init__.pyi` stubs. |
72 | | -- `mise run upgrade` to refresh dependencies from lockfiles. |
73 | | -- `nox --tags bench` to run benchmark sessions when the project contains benchmarks. |
| 54 | +## 🧱 Template Stack |
74 | 55 |
|
75 | | -## 🔄 Release Workflow |
| 56 | +- 🧰 [`gh:liblaf/copier-shared`](https://github.com/liblaf/copier-shared): repository hygiene, common automation, editor settings, and shared project metadata. |
| 57 | +- 🏷️ [`gh:liblaf/copier-release`](https://github.com/liblaf/copier-release): release PRs, changelog generation, Git tags, GitHub Releases, and publish orchestration. |
| 58 | +- 🐍 [`gh:liblaf/copier-python`](https://github.com/liblaf/copier-python): Python packaging, docs, tests, benchmarks, and PyPI workflow wiring. |
76 | 59 |
|
77 | | -For repositories bootstrapped with `copier-release`, the default release flow is: |
| 60 | +## 🚢 Release Workflow |
78 | 61 |
|
79 | | -1. Conventional Commits on `main` trigger `release-pr.yaml`, which opens a release PR with an updated changelog. |
80 | | -2. Review and approve the release PR, or wait for the scheduled auto-review. [`mergery[bot]`](https://github.com/apps/mergery) merges the PR. |
81 | | -3. After the release PR is merged, `release-draft.yaml` creates a draft release. |
82 | | -4. `python-release.yaml` builds the package, publishes it to PyPI with OIDC, and uploads the release assets to the draft release. |
83 | | -5. `release-publish.yaml` publishes the draft release after 6 hours, which gives the release jobs time to finish. |
| 62 | +In a generated project, the default release flow looks like this: |
| 63 | + |
| 64 | +1. Push commits using Conventional Commits. |
| 65 | +2. `release-pr.yaml` creates a release PR with the changelog and updated version. |
| 66 | +3. Merge the release PR yourself, or approve it and let [`mergery[bot]`](https://github.com/apps/mergery) merge it once the button is green. |
| 67 | +4. `release-draft.yaml` creates a draft release. |
| 68 | +5. `python-release.yaml` builds the package, publishes it to PyPI with GitHub OIDC, and uploads release assets to the draft release. |
| 69 | +6. `release-publish.yaml` publishes the draft release after 6 hours so the release jobs have enough time to finish. |
84 | 70 |
|
85 | 71 | ## 🛠️ Post Setup |
86 | 72 |
|
87 | | -### Read the Docs |
| 73 | +### 📚 Read the Docs |
88 | 74 |
|
89 | 75 | 1. Visit <https://app.readthedocs.org/dashboard/import/>. |
90 | | -2. Follow the prompts to import the repository. |
91 | | -3. In project settings, configure: |
| 76 | +2. Follow the prompts to import the generated repository. |
| 77 | +3. Configure these settings: |
92 | 78 |
|
93 | | -| Location | Value | |
94 | | -| ------------------------------------ | --------------------------------------------- | |
95 | | -| `Setup > Settings > Default version` | `stable` | |
96 | | -| `Setup > Settings` | Enable `Build pull requests for this project` | |
97 | | -| `Setup > Addons > Analytics` | Enable | |
98 | | -| `Setup > Addons > Link previews` | Enable | |
99 | | -| `Building > Pull request builds` | Enable `Build pull requests for this project` | |
100 | | -| `Building > Pull request builds` | Enable `Show build overview in a comment` | |
| 79 | +| Location | Value | |
| 80 | +| --- | --- | |
| 81 | +| `Setup > Settings > Default version` | `stable` | |
| 82 | +| `Setup > Settings` | Enable `Build pull requests for this project` | |
| 83 | +| `Setup > Addons > Analytics` | Enable | |
| 84 | +| `Setup > Addons > Link previews` | Enable | |
| 85 | +| `Building > Pull request builds` | Enable `Build pull requests for this project` | |
| 86 | +| `Building > Pull request builds` | Enable `Show build overview in a comment` | |
101 | 87 |
|
102 | | -4. Add an automation rule with: |
| 88 | +4. Add this automation rule: |
103 | 89 |
|
104 | | -| Field | Value | |
105 | | -| -------------- | --------------------- | |
106 | | -| `Description` | `Semantic Versioning` | |
107 | | -| `Match` | `SemVer versions` | |
108 | | -| `Version type` | `Tag` | |
109 | | -| `Action` | `Activate version` | |
| 90 | +| Field | Value | |
| 91 | +| --- | --- | |
| 92 | +| `Description` | `Semantic Versioning` | |
| 93 | +| `Match` | `SemVer versions` | |
| 94 | +| `Version type` | `Tag` | |
| 95 | +| `Action` | `Activate version` | |
110 | 96 |
|
111 | | -### PyPI Publish |
| 97 | +### 📦 PyPI Trusted Publishing |
112 | 98 |
|
113 | 99 | 1. Visit <https://pypi.org/manage/account/publishing/>. |
114 | | -2. Add a trusted publisher for the generated repository. |
115 | | -3. Use the GitHub Actions workflow and environment from the generated release setup: |
116 | | - |
117 | | -| Field | Value | |
118 | | -| ------------------ | ------------------ | |
119 | | -| `Workflow name` | `Python / Release` | |
120 | | -| `Environment name` | `PyPI` | |
| 100 | +2. Create a trusted publisher for the generated repository. |
| 101 | +3. Point it at the GitHub Actions release workflow created by this template stack. |
121 | 102 |
|
122 | | -The remaining form fields should match the GitHub owner, repository, and PyPI project name generated for your package. |
| 103 | +This template publishes with GitHub OIDC, so you do not need a long-lived PyPI API token. |
123 | 104 |
|
124 | 105 | ## 🤝 Contributing |
125 | 106 |
|
126 | | -Contributions are welcome. If you want to improve the template, update the files under [`template/`](https://github.com/liblaf/copier-python/tree/main/template) and any shared helper files used during generation, then keep commit messages in Conventional Commits format so the release automation can do its job. |
| 107 | +To improve the template, edit the files under [`template/`](https://github.com/liblaf/copier-python/tree/main/template) and the small helper files around it, then keep commit messages in Conventional Commits format so the release automation can do its job cleanly. |
127 | 108 |
|
128 | 109 | [](https://github.com/liblaf/copier-python/pulls) |
129 | 110 |
|
130 | | -[](https://github.com/liblaf/copier-python/graphs/contributors) |
| 111 | +[](https://github.com/liblaf/copier-python/graphs/contributors) |
131 | 112 |
|
132 | 113 | ## 🔗 More Copier Templates |
133 | 114 |
|
|
0 commit comments