A copier/cookiecutter template for new Python projects based on the Scientific Python Developer Guide. What makes this different from other templates for Python packages?
github.com
url (the default), and
adds experimental GitLab CI support otherwise.sp-repo-review
to evaluate existing repos against the
guidelines, with a WebAssembly version integrated with the guide. All checks
cross-linked.Be sure you have read the Scientific-Python Development Guide first, and
possibly used them on a project or two. This is not a minimal example or
tutorial. It is a collection of useful tooling for starting a new project using
cookiecutter, or for copying in individual files for an existing project (by
hand, from {{cookiecutter.project_name}}/
).
During generation you can select from the following backends for your package:
Currently, the best choice is probably hatch for pure Python projects, and scikit-build (such as the scikit-build-core + pybind11 choice) for binary projects.
Install copier
and copier-templates-extensions
. Using pipx, that's:
pipx install copier
pipx inject copier copier-templates-extensions
Now, run copier to generate your project:
copier copy gh:scientific-python/cookie <pkg> --trust
(<pkg>
is the path to put the new project. If copier is old, use --UNSAFE
instead of --trust
)
You will get a nicer CLI experience with answer validation. You will also get a
.copier-answers.yml
file, which will allow you to perform updates in the
future.
Note: Add
--vcs-ref=HEAD
to get the latest version instead of the last tagged version; HEAD always passes tests (and is what cookiecutter uses).
Install cookiecutter, ideally with brew install cookiecutter
if you use brew,
otherwise with pipx install cookiecutter
(or prepend pipx run
to the command
below, and skip installation). Then run:
cookiecutter gh:scientific-python/cookie
If you are using cookiecutter 2.2.3+, you will get nice descriptions for the options like copier!
You can also use cruft, which adds the ability update to cookiecutter
projects. Install with pipx install cruft
(or prepend pipx run
to the
command below, and skip installation). Then run:
cruft create gh:scientific-python/cookie
Check the key setup files, pyproject.toml
, and possibly setup.cfg
and
setup.py
(pybind11 example). Update README.md
. Also update and add docs to
docs/
.
There are a few example dependencies and a minimum Python version of 3.9, feel free to change it to whatever you actually need/want. There is also a basic backports structure with a small typing example.
[docs]
extra[test]
extraYou can test locally with nox:
# See all commands
nox -l
# Run a specific check
nox -s "lint(scikit-build)"
# Run a noxfile command on the project noxfile
nox -s "nox(hatch)" -- docs
If you don't have nox
locally, you can use pipx, such as pipx run nox
instead.
Hypermodern-Python is another project worth checking out with many similarities, like great documentation for each feature and many of the same tools used. It has a slightly different set of features, and has a stronger focus on GitHub Actions - most our guide could be adapted to a different CI system fairly easily if you don't want to use GHA. It also forces the use of Poetry (instead of having a backend selection), and doesn't support compiled projects. It currently dumps all development dependencies into a shared environment, causing long solve times and high chance of conflicts. It also does not use pre-commit the way it was intended to be used. It also has quite a bit of custom code.
A lot of the guide, cookiecutter, and repo-review started out as part of Scikit-HEP. These projects were merged, generalized, and combined with the NSLS-II guide during the 2023 Scientific-Python Developers Summit.
sp-repo-review
provides checks based on the [Scientific-Python
Development Guide][] at scientific-python/cookie for repo-review.
This tool can check the style of a repository. Use like this:
pipx run 'sp-repo-review[cli]' <path to repository>
This will produce a list of results - green checkmarks mean this rule is followed, red x’s mean the rule is not. A yellow warning sign means that the check was skipped because a previous required check failed. Some checks will fail, that’s okay - the goal is bring all possible issues to your attention, not to force compliance with arbitrary checks. Eventually there might be a way to mark checks as ignored.
For example, GH101
expects all your action files to have a nice name:
field.
If you are happy with the file-based names you see in CI, you should feel free
to simply ignore this check (just visually ignore it for the moment, a way to
specify ignored checks will likely be added eventually).
All checks are mentioned at least in some way in the [Scientific-Python
Development Guide][]. You should read that first - if you are not attempting to
follow them, some of the checks might not work. For example, the guidelines
specify pytest configuration be placed in pyproject.toml
. If you place it
somewhere else, then all the pytest checks will be skipped.
This was originally developed for Scikit-HEP before moving to Scientific Python.
You can also use GitHub Actions:
- uses: scientific-python/cookie@<version>
Or pre-commit:
- repo: https://github.com/scientific-python/cookie
rev: <version>
hooks:
- id: sp-repo-review
If you use additional_dependencies
to add more plugins, like
validate-pyproject
, you should also include "repo-review[cli]"
to ensure the
CLI requirements are included.
PY001
: Has a pyproject.tomlPY002
: Has a README.(md|rst) filePY003
: Has a LICENSE* filePY004
: Has docs folderPY005
: Has tests folderPY006
: Has pre-commit configPY007
: Supports an easy task runner (nox, tox, pixi, etc.)PP002
: Has a proper build-system tablePP003
: Does not list wheel as a build-depPP004
: Does not upper cap Python requiresPP301
: Has pytest in pyprojectPP302
: Sets a minimum pytest to at least 6PP303
: Sets the test pathsPP304
: Sets the log level in pytestPP305
: Specifies xfail_strictPP306
: Specifies strict configPP307
: Specifies strict markersPP308
: Specifies useful pytest summaryPP309
: Filter warnings specifiedRTD100
: Uses ReadTheDocs (pyproject config)RTD101
: You have to set the RTD version number to 2RTD102
: You have to set the RTD build imageRTD103
: You have to set the RTD python versionGH100
: Has GitHub Actions configGH101
: Has nice namesGH102
: Auto-cancel on repeated PRsGH103
: At least one workflow with manual dispatch triggerGH104
: Use unique names for upload-artifactGH200
: Maintained by DependabotGH210
: Maintains the GitHub action versions with DependabotGH211
: Do not pin core actions as major versionsGH212
: Require GHA update groupingMY100
: Uses MyPy (pyproject config)MY101
: MyPy strict modeMY102
: MyPy show_error_codes deprecatedMY103
: MyPy warn unreachableMY104
: MyPy enables ignore-without-codeMY105
: MyPy enables redundant-exprMY106
: MyPy enables truthy-boolPC100
: Has pre-commit-hooksPC110
: Uses black or ruff-formatPC111
: Uses blacken-docsPC140
: Uses a type checkerPC160
: Uses a spell checkerPC170
: Uses PyGrep hooks (only needed if rST present)PC180
: Uses a markdown formatterPC190
: Uses RuffPC191
: Ruff show fixes if fixes enabledPC901
: Custom pre-commit CI messageRF001
: Has Ruff configRF002
: Target version must be setRF003
: src directory doesn't need to be specified anymore (0.6+)RF101
: Bugbear must be selectedRF102
: isort must be selectedRF103
: pyupgrade must be selectedRF201
: Avoid using deprecated config settingsRF202
: Use (new) lint config section