cookiecutter-pypackage-gitlab 0.1.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.
- cookiecutter_pypackage_gitlab-0.1.0/LICENSE +48 -0
- cookiecutter_pypackage_gitlab-0.1.0/PKG-INFO +215 -0
- cookiecutter_pypackage_gitlab-0.1.0/README.md +184 -0
- cookiecutter_pypackage_gitlab-0.1.0/pyproject.toml +187 -0
- cookiecutter_pypackage_gitlab-0.1.0/setup.cfg +4 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/__init__.py +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/__main__.py +5 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/cli.py +88 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/cookiecutter.json +52 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/hooks/__init__.py +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/hooks/post_gen_project.py +2 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/hooks/pre_gen_project.py +261 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/local_extensions.py +185 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.editorconfig +27 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.gitignore +167 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.gitlab/issue_templates/bug_report.md +39 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.gitlab/issue_templates/feature_request.md +26 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.gitlab/issue_templates/question.md +27 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.gitlab-ci.yml +286 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/.pre-commit-config.yaml +43 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/CODE_OF_CONDUCT.md +102 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/CONTRIBUTING.md +134 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/HISTORY.md +5 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/LICENSE +21 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/Makefile +204 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/README.md +115 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/api.md +3 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/index.md +14 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/installation.md +43 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/registry_setup.md +103 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/release_checklist.md +62 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/troubleshooting.md +137 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/docs/usage.md +7 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/pyproject.toml +149 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/__init__.py +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/__main__.py +4 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/api.py +17 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/cli.py +24 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/py.typed +0 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/src/{{cookiecutter.import_package_name}}/utils.py +2 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/tests/test_{{cookiecutter.import_package_name}}.py +12 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab/template/{{cookiecutter.local_repo_dir}}/zensical.toml +39 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/PKG-INFO +215 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/SOURCES.txt +52 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/dependency_links.txt +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/entry_points.txt +2 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/requires.txt +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/src/cookiecutter_pypackage_gitlab.egg-info/top_level.txt +1 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_bake_project.py +148 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_cli.py +167 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_cookiecutter_json.py +93 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_local_extensions.py +191 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_pre_gen_hook.py +297 -0
- cookiecutter_pypackage_gitlab-0.1.0/tests/test_readme_author.py +90 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scott Karlin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
-----------------------------------------------------------------------------
|
|
24
|
+
Original license for v0.4.0 of audreyfeldroy/cookiecutter-pypackage from
|
|
25
|
+
which substantial portions are incorporated into
|
|
26
|
+
sck/cookiecutter-pypackage-gitlab:
|
|
27
|
+
|
|
28
|
+
MIT License
|
|
29
|
+
|
|
30
|
+
Copyright (c) 2025 Audrey M. Roy Greenfeld
|
|
31
|
+
|
|
32
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
33
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
34
|
+
in the Software without restriction, including without limitation the rights
|
|
35
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
36
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
37
|
+
furnished to do so, subject to the following conditions:
|
|
38
|
+
|
|
39
|
+
The above copyright notice and this permission notice shall be included in all
|
|
40
|
+
copies or substantial portions of the Software.
|
|
41
|
+
|
|
42
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
43
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
44
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
45
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
46
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
47
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
48
|
+
SOFTWARE.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cookiecutter-pypackage-gitlab
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cookiecutter template for a Python package in the GitLab ecosystem
|
|
5
|
+
Author-email: Scott Karlin <pypi@karlin-online.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: homepage, https://gitlab.com/sck/cookiecutter-pypackage-gitlab
|
|
8
|
+
Project-URL: bugs, https://gitlab.com/sck/cookiecutter-pypackage-gitlab/issues
|
|
9
|
+
Project-URL: changelog, https://gitlab.com/sck/cookiecutter-pypackage-gitlab/blob/main/HISTORY.md
|
|
10
|
+
Project-URL: documentation, https://sck.gitlab.io/cookiecutter-pypackage-gitlab/
|
|
11
|
+
Keywords: cookiecutter,template,package,gitlab
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.12
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: cookiecutter>=2.6.0
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# Cookiecutter PyPackage GitLab
|
|
33
|
+
|
|
34
|
+
[Cookiecutter](https://github.com/cookiecutter/cookiecutter) template for a
|
|
35
|
+
Python package in the GitLab CI/CD ecosystem.
|
|
36
|
+
|
|
37
|
+
* GitLab repo: https://gitlab.com/sck/cookiecutter-pypackage-gitlab/
|
|
38
|
+
* Free software: MIT license
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
* Dependency management with [uv](https://docs.astral.sh/uv/)
|
|
43
|
+
* Task running with [make](https://www.gnu.org/software/make/)
|
|
44
|
+
* Testing with [pytest](https://docs.pytest.org/) under GitLab CI
|
|
45
|
+
* Auto-publish to package repository when you push a `v*` tag.
|
|
46
|
+
(For [PyPI](https://pypi.org/) no API tokens are needed by using
|
|
47
|
+
[Trusted Publishers](https://docs.pypi.org/trusted-publishers/).)
|
|
48
|
+
* Hardened GitLab CI workflows: version-pinned Docker images
|
|
49
|
+
* Documentation site built with [Zensical](https://zensical.org/) and
|
|
50
|
+
auto-deployed to
|
|
51
|
+
[GitLab Pages](https://docs.gitlab.com/user/project/pages/).
|
|
52
|
+
* Linting with [ruff](https://docs.astral.sh/ruff/), type checking with
|
|
53
|
+
[mypy](https://mypy.readthedocs.io) and [ty](https://docs.astral.sh/ty/)
|
|
54
|
+
* Command line interface using
|
|
55
|
+
[argparse](https://docs.python.org/3/library/argparse.html)
|
|
56
|
+
|
|
57
|
+
## Quickstart
|
|
58
|
+
|
|
59
|
+
Generate a new Python package by creating a temporary venv, installing the
|
|
60
|
+
package, and running the command.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python -m venv venv
|
|
64
|
+
source venv/bin/activate
|
|
65
|
+
pip install cookiecutter-pypackage-gitlab
|
|
66
|
+
cookiecutter-pypackage-gitlab
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If you have [`uvx`](https://docs.astral.sh/uv/getting-started/installation/)
|
|
70
|
+
installed, you can also use it to run `cookiecutter-pypackage-gitlab` without
|
|
71
|
+
explicitly creating a temporary venv, installing the package, running the
|
|
72
|
+
package, and then removing the temporary venv:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uvx cookiecutter-pypackage-gitlab
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
You'll be prompted for some values:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
[1/14] Project name for documentation (spaces allowed) (Python Boilerplate): My Package
|
|
82
|
+
[2/14] Project short description for pyproject.toml and docs (Python Boilerplate contains all the boilerplate you need to create a Python package in the GitLab ecosystem.): A short description of your package.
|
|
83
|
+
[3/14] Initial version string for the package (0.0.0):
|
|
84
|
+
[4/14] Author full name (Scott Karlin): Your Name
|
|
85
|
+
[5/14] Author email (scottkarlin@example.com): you@example.com
|
|
86
|
+
[6/14] Author GitLab username (sck): your-gitlab-username
|
|
87
|
+
[7/14] Author website (https://gitlab.com/your-gitlab-username):
|
|
88
|
+
[8/14] PyPI Package Name for pip install (no spaces; recommend normalized form) (my-package):
|
|
89
|
+
[9/14] GitLab repository URL for this project. (https://gitlab.com/your-gitlab-username/my-package):
|
|
90
|
+
[10/14] Display name of the project in GitLab (my-package):
|
|
91
|
+
[11/14] Python import package name (my_package):
|
|
92
|
+
[12/14] Target package registry: "pypi" to publish to PyPI or "gitlab" to publish to your GitLab project's package registry (gitlab):
|
|
93
|
+
[13/14] PyPI username (required when publish_registry is "pypi") ():
|
|
94
|
+
[14/14] The name of the local repo directory (my-package):
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then:
|
|
98
|
+
|
|
99
|
+
* Create a GitLab repo and push your code
|
|
100
|
+
* Enable GitLab Pages: Settings > Pages > Source: **GitLab CI**
|
|
101
|
+
* Set up
|
|
102
|
+
[PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
|
|
103
|
+
for your repo
|
|
104
|
+
* Release your package: see
|
|
105
|
+
[Release Checklist](docs/release_checklist.md) for the workflow.
|
|
106
|
+
|
|
107
|
+
See the **[full documentation](https://sck.gitlab.io/cookiecutter-pypackage-gitlab/)**
|
|
108
|
+
for the tutorial, CI/CD reference, design notes, and more.
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
To set up for local development:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git clone git@gitlab.com:sck/cookiecutter-pypackage-gitlab.git
|
|
116
|
+
cd cookiecutter-pypackage-gitlab
|
|
117
|
+
make venv
|
|
118
|
+
source venv/bin/activate
|
|
119
|
+
make init
|
|
120
|
+
make uv.lock
|
|
121
|
+
make sync-devci
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Run quality checks (format, lint, type check, test):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
make qa
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Watch the template for changes and auto-regenerate `python-boilerplate/` in the
|
|
131
|
+
repo root (useful when iterating on template files):
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
make template-watch
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Release cycle
|
|
138
|
+
|
|
139
|
+
1. Edit code and add change notes to the `Next Release (TBD)` entry in
|
|
140
|
+
`HISTORY.md` as you go.
|
|
141
|
+
|
|
142
|
+
2. When ready to release, upgrade all dependencies and refresh the environment:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
make update
|
|
146
|
+
make sync-devci
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
3. Run the full quality check suite:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
make qa
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
4. In `HISTORY.md`, replace the `Next Release (TBD)` heading with the release
|
|
156
|
+
version and today's date, and verify the change notes are complete.
|
|
157
|
+
|
|
158
|
+
5. Sync the version to `pyproject.toml` and `uv.lock`:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
make set-version
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
6. Commit the release:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
git commit -am "Release X.Y.Z"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
7. Tag and push. `make tag` validates version consistency across `HISTORY.md`,
|
|
171
|
+
`pyproject.toml`, and `uv.lock`; creates an annotated tag; pushes it to
|
|
172
|
+
`origin`; and adds a new `Next Release (TBD)` entry to `HISTORY.md`:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
make tag
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Pushing the tag triggers the GitLab CI/CD publish job, which uploads
|
|
179
|
+
the package to your selected registry.
|
|
180
|
+
|
|
181
|
+
8. Commit to open the next development cycle:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
git commit -am "Start next development cycle"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
9. Go back to step 1.
|
|
188
|
+
|
|
189
|
+
See also [Release Checklist](docs/release_checklist.md) for
|
|
190
|
+
registry-specific publishing notes and troubleshooting.
|
|
191
|
+
|
|
192
|
+
## Not Exactly What You Want?
|
|
193
|
+
|
|
194
|
+
Don't worry, you have options:
|
|
195
|
+
|
|
196
|
+
### Fork This / Create Your Own
|
|
197
|
+
|
|
198
|
+
If you have differences in your preferred setup, I encourage you to fork this
|
|
199
|
+
to create your own version.
|
|
200
|
+
Or create your own; it doesn't strictly have to be a fork.
|
|
201
|
+
|
|
202
|
+
### Similar Cookiecutter Templates
|
|
203
|
+
|
|
204
|
+
This cookiecutter template was based on the v0.4.0 (2026-02-16) release of
|
|
205
|
+
[Cookiecutter PyPackage](https://github.com/audreyfeldroy/cookiecutter-pypackage)
|
|
206
|
+
(a GitHub-centric template).
|
|
207
|
+
That package lists other forks you can explore to get ideas at
|
|
208
|
+
[network](https://github.com/audreyfeldroy/cookiecutter-pypackage/network)
|
|
209
|
+
and
|
|
210
|
+
[family tree](https://github.com/audreyfeldroy/cookiecutter-pypackage/network/members).
|
|
211
|
+
|
|
212
|
+
### Or Submit a Merge Request
|
|
213
|
+
|
|
214
|
+
I also accept merge requests on this, if they're small, atomic, follow my
|
|
215
|
+
design decisions, and if they make my own packaging experience better.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Cookiecutter PyPackage GitLab
|
|
2
|
+
|
|
3
|
+
[Cookiecutter](https://github.com/cookiecutter/cookiecutter) template for a
|
|
4
|
+
Python package in the GitLab CI/CD ecosystem.
|
|
5
|
+
|
|
6
|
+
* GitLab repo: https://gitlab.com/sck/cookiecutter-pypackage-gitlab/
|
|
7
|
+
* Free software: MIT license
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
* Dependency management with [uv](https://docs.astral.sh/uv/)
|
|
12
|
+
* Task running with [make](https://www.gnu.org/software/make/)
|
|
13
|
+
* Testing with [pytest](https://docs.pytest.org/) under GitLab CI
|
|
14
|
+
* Auto-publish to package repository when you push a `v*` tag.
|
|
15
|
+
(For [PyPI](https://pypi.org/) no API tokens are needed by using
|
|
16
|
+
[Trusted Publishers](https://docs.pypi.org/trusted-publishers/).)
|
|
17
|
+
* Hardened GitLab CI workflows: version-pinned Docker images
|
|
18
|
+
* Documentation site built with [Zensical](https://zensical.org/) and
|
|
19
|
+
auto-deployed to
|
|
20
|
+
[GitLab Pages](https://docs.gitlab.com/user/project/pages/).
|
|
21
|
+
* Linting with [ruff](https://docs.astral.sh/ruff/), type checking with
|
|
22
|
+
[mypy](https://mypy.readthedocs.io) and [ty](https://docs.astral.sh/ty/)
|
|
23
|
+
* Command line interface using
|
|
24
|
+
[argparse](https://docs.python.org/3/library/argparse.html)
|
|
25
|
+
|
|
26
|
+
## Quickstart
|
|
27
|
+
|
|
28
|
+
Generate a new Python package by creating a temporary venv, installing the
|
|
29
|
+
package, and running the command.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m venv venv
|
|
33
|
+
source venv/bin/activate
|
|
34
|
+
pip install cookiecutter-pypackage-gitlab
|
|
35
|
+
cookiecutter-pypackage-gitlab
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you have [`uvx`](https://docs.astral.sh/uv/getting-started/installation/)
|
|
39
|
+
installed, you can also use it to run `cookiecutter-pypackage-gitlab` without
|
|
40
|
+
explicitly creating a temporary venv, installing the package, running the
|
|
41
|
+
package, and then removing the temporary venv:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uvx cookiecutter-pypackage-gitlab
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You'll be prompted for some values:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
[1/14] Project name for documentation (spaces allowed) (Python Boilerplate): My Package
|
|
51
|
+
[2/14] Project short description for pyproject.toml and docs (Python Boilerplate contains all the boilerplate you need to create a Python package in the GitLab ecosystem.): A short description of your package.
|
|
52
|
+
[3/14] Initial version string for the package (0.0.0):
|
|
53
|
+
[4/14] Author full name (Scott Karlin): Your Name
|
|
54
|
+
[5/14] Author email (scottkarlin@example.com): you@example.com
|
|
55
|
+
[6/14] Author GitLab username (sck): your-gitlab-username
|
|
56
|
+
[7/14] Author website (https://gitlab.com/your-gitlab-username):
|
|
57
|
+
[8/14] PyPI Package Name for pip install (no spaces; recommend normalized form) (my-package):
|
|
58
|
+
[9/14] GitLab repository URL for this project. (https://gitlab.com/your-gitlab-username/my-package):
|
|
59
|
+
[10/14] Display name of the project in GitLab (my-package):
|
|
60
|
+
[11/14] Python import package name (my_package):
|
|
61
|
+
[12/14] Target package registry: "pypi" to publish to PyPI or "gitlab" to publish to your GitLab project's package registry (gitlab):
|
|
62
|
+
[13/14] PyPI username (required when publish_registry is "pypi") ():
|
|
63
|
+
[14/14] The name of the local repo directory (my-package):
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Then:
|
|
67
|
+
|
|
68
|
+
* Create a GitLab repo and push your code
|
|
69
|
+
* Enable GitLab Pages: Settings > Pages > Source: **GitLab CI**
|
|
70
|
+
* Set up
|
|
71
|
+
[PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
|
|
72
|
+
for your repo
|
|
73
|
+
* Release your package: see
|
|
74
|
+
[Release Checklist](docs/release_checklist.md) for the workflow.
|
|
75
|
+
|
|
76
|
+
See the **[full documentation](https://sck.gitlab.io/cookiecutter-pypackage-gitlab/)**
|
|
77
|
+
for the tutorial, CI/CD reference, design notes, and more.
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
To set up for local development:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone git@gitlab.com:sck/cookiecutter-pypackage-gitlab.git
|
|
85
|
+
cd cookiecutter-pypackage-gitlab
|
|
86
|
+
make venv
|
|
87
|
+
source venv/bin/activate
|
|
88
|
+
make init
|
|
89
|
+
make uv.lock
|
|
90
|
+
make sync-devci
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Run quality checks (format, lint, type check, test):
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
make qa
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Watch the template for changes and auto-regenerate `python-boilerplate/` in the
|
|
100
|
+
repo root (useful when iterating on template files):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
make template-watch
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Release cycle
|
|
107
|
+
|
|
108
|
+
1. Edit code and add change notes to the `Next Release (TBD)` entry in
|
|
109
|
+
`HISTORY.md` as you go.
|
|
110
|
+
|
|
111
|
+
2. When ready to release, upgrade all dependencies and refresh the environment:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
make update
|
|
115
|
+
make sync-devci
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
3. Run the full quality check suite:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
make qa
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
4. In `HISTORY.md`, replace the `Next Release (TBD)` heading with the release
|
|
125
|
+
version and today's date, and verify the change notes are complete.
|
|
126
|
+
|
|
127
|
+
5. Sync the version to `pyproject.toml` and `uv.lock`:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
make set-version
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
6. Commit the release:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git commit -am "Release X.Y.Z"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
7. Tag and push. `make tag` validates version consistency across `HISTORY.md`,
|
|
140
|
+
`pyproject.toml`, and `uv.lock`; creates an annotated tag; pushes it to
|
|
141
|
+
`origin`; and adds a new `Next Release (TBD)` entry to `HISTORY.md`:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
make tag
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Pushing the tag triggers the GitLab CI/CD publish job, which uploads
|
|
148
|
+
the package to your selected registry.
|
|
149
|
+
|
|
150
|
+
8. Commit to open the next development cycle:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git commit -am "Start next development cycle"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
9. Go back to step 1.
|
|
157
|
+
|
|
158
|
+
See also [Release Checklist](docs/release_checklist.md) for
|
|
159
|
+
registry-specific publishing notes and troubleshooting.
|
|
160
|
+
|
|
161
|
+
## Not Exactly What You Want?
|
|
162
|
+
|
|
163
|
+
Don't worry, you have options:
|
|
164
|
+
|
|
165
|
+
### Fork This / Create Your Own
|
|
166
|
+
|
|
167
|
+
If you have differences in your preferred setup, I encourage you to fork this
|
|
168
|
+
to create your own version.
|
|
169
|
+
Or create your own; it doesn't strictly have to be a fork.
|
|
170
|
+
|
|
171
|
+
### Similar Cookiecutter Templates
|
|
172
|
+
|
|
173
|
+
This cookiecutter template was based on the v0.4.0 (2026-02-16) release of
|
|
174
|
+
[Cookiecutter PyPackage](https://github.com/audreyfeldroy/cookiecutter-pypackage)
|
|
175
|
+
(a GitHub-centric template).
|
|
176
|
+
That package lists other forks you can explore to get ideas at
|
|
177
|
+
[network](https://github.com/audreyfeldroy/cookiecutter-pypackage/network)
|
|
178
|
+
and
|
|
179
|
+
[family tree](https://github.com/audreyfeldroy/cookiecutter-pypackage/network/members).
|
|
180
|
+
|
|
181
|
+
### Or Submit a Merge Request
|
|
182
|
+
|
|
183
|
+
I also accept merge requests on this, if they're small, atomic, follow my
|
|
184
|
+
design decisions, and if they make my own packaging experience better.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cookiecutter-pypackage-gitlab"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Cookiecutter template for a Python package in the GitLab ecosystem"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Scott Karlin", email = "pypi@karlin-online.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [ "cookiecutter", "template", "package", "gitlab" ]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Natural Language :: English",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Programming Language :: Python",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
29
|
+
"Topic :: Software Development :: Code Generators",
|
|
30
|
+
"Typing :: Typed",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"cookiecutter>=2.6.0", # template_watch.py, src/cookiecutter_pypackage_gitlab/cli.py
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[dependency-groups]
|
|
37
|
+
devci = [
|
|
38
|
+
{ include-group = "init" },
|
|
39
|
+
{ include-group = "lint" },
|
|
40
|
+
{ include-group = "test" },
|
|
41
|
+
{ include-group = "typecheck" },
|
|
42
|
+
{ include-group = "tools" },
|
|
43
|
+
]
|
|
44
|
+
init = [
|
|
45
|
+
"pip",
|
|
46
|
+
"pre-commit",
|
|
47
|
+
"setuptools",
|
|
48
|
+
"uv",
|
|
49
|
+
"wheel",
|
|
50
|
+
]
|
|
51
|
+
lint = [
|
|
52
|
+
"ruff",
|
|
53
|
+
]
|
|
54
|
+
test = [
|
|
55
|
+
"coverage",
|
|
56
|
+
"pytest",
|
|
57
|
+
"pytest-cookies",
|
|
58
|
+
]
|
|
59
|
+
typecheck = [
|
|
60
|
+
"mypy",
|
|
61
|
+
"ty",
|
|
62
|
+
]
|
|
63
|
+
docs = [
|
|
64
|
+
"mkdocstrings[python]",
|
|
65
|
+
"zensical",
|
|
66
|
+
]
|
|
67
|
+
tools = [
|
|
68
|
+
"watchdog>=6.0.0", # template_watch.py
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[project.scripts]
|
|
72
|
+
cookiecutter-pypackage-gitlab = "cookiecutter_pypackage_gitlab.cli:main"
|
|
73
|
+
|
|
74
|
+
[project.urls]
|
|
75
|
+
homepage = "https://gitlab.com/sck/cookiecutter-pypackage-gitlab"
|
|
76
|
+
bugs = "https://gitlab.com/sck/cookiecutter-pypackage-gitlab/issues"
|
|
77
|
+
changelog = "https://gitlab.com/sck/cookiecutter-pypackage-gitlab/blob/main/HISTORY.md"
|
|
78
|
+
documentation = "https://sck.gitlab.io/cookiecutter-pypackage-gitlab/"
|
|
79
|
+
|
|
80
|
+
[tool.coverage.run]
|
|
81
|
+
branch = true
|
|
82
|
+
parallel = true
|
|
83
|
+
source = ["src/", "tests/"]
|
|
84
|
+
|
|
85
|
+
[tool.coverage.report]
|
|
86
|
+
show_missing = true
|
|
87
|
+
skip_covered = true
|
|
88
|
+
fail_under = 50
|
|
89
|
+
exclude_also = [
|
|
90
|
+
"if TYPE_CHECKING:",
|
|
91
|
+
"if typing.TYPE_CHECKING:",
|
|
92
|
+
"@overload",
|
|
93
|
+
"@typing.overload",
|
|
94
|
+
"class .*\\bProtocol\\):",
|
|
95
|
+
"@(abc\\.)?abstractmethod",
|
|
96
|
+
"raise NotImplementedError",
|
|
97
|
+
"\\.\\.\\.",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.mypy]
|
|
101
|
+
explicit_package_bases = true
|
|
102
|
+
mypy_path = "src/cookiecutter_pypackage_gitlab/template/hooks"
|
|
103
|
+
files = "src/cookiecutter_pypackage_gitlab, ./tests"
|
|
104
|
+
exclude = [
|
|
105
|
+
".*cookiecutter.local_repo_dir.*",
|
|
106
|
+
"src/cookiecutter_pypackage_gitlab/template",
|
|
107
|
+
]
|
|
108
|
+
strict = true
|
|
109
|
+
disable_error_code = [
|
|
110
|
+
# beat these down (comment out) one-by-one
|
|
111
|
+
#"abstract",
|
|
112
|
+
#"arg-type", # ignoring 2
|
|
113
|
+
#"assignment",
|
|
114
|
+
#"attr-defined",
|
|
115
|
+
#"call-arg",
|
|
116
|
+
#"comparison-overlap",
|
|
117
|
+
"import-untyped",
|
|
118
|
+
#"index",
|
|
119
|
+
#"misc", # ignoring 1
|
|
120
|
+
#"no-any-return",
|
|
121
|
+
#"no-redef",
|
|
122
|
+
"no-untyped-call",
|
|
123
|
+
"no-untyped-def",
|
|
124
|
+
#"operator",
|
|
125
|
+
#"override",
|
|
126
|
+
#"redundant-cast",
|
|
127
|
+
#"return-value",
|
|
128
|
+
#"type-arg",
|
|
129
|
+
#"type-var",
|
|
130
|
+
#"union-attr",
|
|
131
|
+
#"valid-type",
|
|
132
|
+
#"var-annotated",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[[tool.mypy.overrides]]
|
|
136
|
+
module = "local_extensions"
|
|
137
|
+
ignore_missing_imports = true
|
|
138
|
+
|
|
139
|
+
[tool.pytest.ini_options]
|
|
140
|
+
testpaths = [
|
|
141
|
+
"tests",
|
|
142
|
+
]
|
|
143
|
+
addopts = "--template src/cookiecutter_pypackage_gitlab/template"
|
|
144
|
+
|
|
145
|
+
[tool.ruff]
|
|
146
|
+
line-length = 120
|
|
147
|
+
exclude = [
|
|
148
|
+
"*cookiecutter.local_repo_dir*"
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
[tool.ruff.lint]
|
|
152
|
+
select = [
|
|
153
|
+
"E", # pycodestyle errors
|
|
154
|
+
"W", # pycodestyle warnings
|
|
155
|
+
"F", # Pyflakes
|
|
156
|
+
"B", # flake8-bugbear
|
|
157
|
+
"UP", # pyupgrade
|
|
158
|
+
]
|
|
159
|
+
ignore = [
|
|
160
|
+
"E501", # line length (handled by ruff format for code)
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
[tool.setuptools.packages.find]
|
|
164
|
+
where = ["src"]
|
|
165
|
+
|
|
166
|
+
[tool.setuptools.package-data]
|
|
167
|
+
"cookiecutter_pypackage_gitlab" = [
|
|
168
|
+
"template/**/*", # all non-hidden files
|
|
169
|
+
"template/**/.*", # dotfiles
|
|
170
|
+
"template/**/.?*/**/*", # files inside hidden directories
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
[tool.ty.environment]
|
|
174
|
+
python = "venv/bin/python"
|
|
175
|
+
extra-paths = [
|
|
176
|
+
"src/cookiecutter_pypackage_gitlab/template",
|
|
177
|
+
"src/cookiecutter_pypackage_gitlab/template/hooks",
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
[tool.ty.src]
|
|
181
|
+
exclude = [
|
|
182
|
+
"src/cookiecutter_pypackage_gitlab/template/**",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[tool.uv]
|
|
186
|
+
python-downloads = "never"
|
|
187
|
+
python-preference = "managed"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Cookiecutter PyPackage GitLab - A modern Python package template for GitLab hosted packages."""
|