Cookiecutter template for a 21cmFAST/MC plugin.
Table of Contents
This is an opinionated template that helps code have a consistent style and easy deployment.
- Pytest for testing
- Github Actions for CI
- Coveralls for code coverage
- Documentation with Sphinx, ready for ReadTheDocs.
- Support for C extensions (including coverage measurement for the C code). See c_extension_support.
- Packaging and code quality checks.
Just do:
pip install cookiecutter
First generate your project:
cookiecutter gh:21cmfast/cookiecutter-21cmfast-plugin
You will be asked for these fields:
Note
Fields that work together usually use the same prefix. If you answer "no" on the first one then the rest won't have any effect so just ignore them. Maybe in the future cookiecutter will allow option hiding or something like a wizard.
Field | Default | Description |
---|---|---|
full_name |
"Ionel Cristian Maries" |
Main author of this library or application (used in Can be set in your |
email |
Contact email of the author (used in Can be set in your |
|
website |
"https://blog.ionelmc.ro" |
Website of the author (used in Can be set in your |
repo_username |
"ionelmc" |
GitHub user name of this project (used for GitHub link). Can be set in your |
project_name |
"Nameless" |
Verbose project name, used in headings (docs, readme, etc). |
repo_hosting_domain |
"github.com" |
Use "no" for no hosting (various links will disappear). You can also use "gitlab.com" and such but various
things will be broken (like Travis configuration). |
repo_name |
"python-nameless" |
Repository name on GitHub (and project's root directory name). |
package_name |
"nameless" |
Python package name (whatever you would import). |
distribution_name |
"nameless" |
PyPI distribution name (what you would pip install ). |
project_short_description |
"An example package [...]" |
One line description of the project (used in README.rst and setup.py ). |
release_date |
"today" |
Release date of the project (ISO 8601 format) default to today (used in CHANGELOG.rst ). |
year |
"now" |
Copyright year (used in Sphinx conf.py ). |
version |
"0.1.0" |
Release version (see .bumpversion.cfg and in Sphinx conf.py ). |
legacy_python |
"no" |
Allow for legacy python versions, like python2.7 . If you do not especially need to support (depreciated) python
versions you should keep it as is. |
c_extension_support |
"no" |
Support C extensions (will slighly change the outputted
|
c_extension_optional |
"no" |
Make C extensions optional (will allow your package to install even if extensions can't be compiled) |
c_extension_test_pypi |
"no" |
Enables wheel publishing to https://test.pypi.org/ by using tox-wheel and manylinux1. You should only use this with |
test_matrix_configurator |
"no" |
Enable the test matrix generator script. If you don't have a huge number of test environments then probably you don't need this. |
test_matrix_separate_coverage |
"no" |
Enable this to have a separate env for measuring coverage. Indicated if you want to run doctests or collect tests
from Note that |
test_runner |
"pytest" |
Test runner to use. Available options: pytest or nose . |
setup_py_uses_test_runner |
"no" |
Whether to use the test_runner for python setup.py test.
Note that this will also add to setup_requires if a test-runner is needed. |
setup_py_uses_setuptools_scm |
"no" |
Enables the use of setuptools-scm. You can continue using bumpversion with this enabled. Recommended if you use |
allow_tests_inside_package |
"no" |
Collect tests that are inside the package (in other works, tests that are installed with the package). The outside of package tests directory will still exist and be collected. |
linter |
"flake8" | Linter to use for tox -e check . Available options: flake8 or pylama |
pre_commit |
"no" | Enable basic pre-commit configuration. |
command_line_interface |
"plain" |
Option to enable a CLI (a bin/executable file). Available options:
|
command_line_interface_bin_name |
"nameless" |
Name of the CLI bin/executable file (set the console script name in setup.py ). |
license |
"BSD license" |
License to use. Available options:
What license to pick? https://choosealicense.com/ |
coveralls |
"no" |
Enable pushing coverage data to Coveralls and add badge in README.rst . |
codecov |
"yes" |
Enable pushing coverage data to Codecov and add badge in Note: Doesn't support pushing C extension coverage yet. |
scrutinizer |
"no" |
Add a Scrutinizer badge in README.rst . |
codacy |
"no" |
Add a Codacy badge in Note: After importing the project in Codacy, find the hexadecimal project ID from settings and replace it in badge URL |
codeclimate |
"no" |
Add a CodeClimate badge in README.rst . |
sphinx_docs |
"yes" |
Have Sphinx documentation. |
sphinx_theme |
"sphinx-rtd-theme" |
What Sphinx theme to use. Suggested alternative: sphinx-py3doc-enhanced-theme <https://pypi.org/project/sphinx_py3doc_enhanced_theme> for a responsive theme based on the Python 3 documentation. |
sphinx_doctest |
"no" |
Set to Read more about doctest support in Sphinx. |
sphinx_docs_hosting |
"repo_name.readthedocs.io" |
Leave as default if your documentation will be hosted on readthedocs. If your documentation will be hosted elsewhere (such as GitHub Pages or GitLab Pages), enter the top-level URL. |
pypi_badge |
"yes" |
By default, this will insert links to your project's page on PyPI.org. Note that if your package is not (yet) on PyPI, this will cause tox -e docs to fail. If you choose "no", then these links will not be created. |
pypi_disable_upload |
"no" |
If you specifically want to be sure your package will never be accidentally uploaded to PyPI, you can pick "yes". |
travis |
"yes" |
If you want the Travis-CI badge and configuration. |
travis_osx |
"no" |
Enables OSX support in the Travis-CI configuration. To keep things simple and easy to understand only Brew Python 2 and 3 will be used. You probably want to enable this if you use |
appveyor |
"yes" |
If you want the AppVeyor badge and configuration. |
requiresio |
"yes" |
If you want the requires.io badge and configuration. |
The testing (tox.ini
and .travis.yml
) configuration is generated from templates. For your convenience there's an
initial bootstrap tox.ini
, to get the initial generation going just run:
tox
You can later regenerate tox.ini
and .travis.yml
by running (if you enabled the test_matrix_configurator
option):
tox -e bootstrap
After this you can create the initial repository (make sure you create an empty Github project):
git init . git add . git commit -m "Initial skel." git remote add origin [email protected]:ionelmc/python-nameless.git git push -u origin master
Then:
- Enable the repository in your Travis CI account.
- Enable the repository in your Coveralls account.
- Add the repo to your ReadTheDocs account + turn on the ReadTheDocs
service hook. Don't forget to enable virtualenv and specify
docs/requirements.txt
as the requirements file in Advanced Settings.
To run all the tests, just run:
tox
To see all the tox environments:
tox -l
To only build the docs:
tox -e docs
To build and verify that the built package is proper and other code QA checks:
tox -e check
Before releasing your package on PyPI you should have all the tox environments passing.
This template provides a basic bumpversion configuration. It's as simple as running:
bumpversion patch
to increase version from 1.0.0 to 1.0.1.bumpversion minor
to increase version from 1.0.0 to 1.1.0.bumpversion major
to increase version from 1.0.0 to 2.0.0.
You should read Semantic Versioning 2.0.0 before bumping versions.
Before building dists make sure you got a clean build area:
rm -rf build rm -rf src/*.egg-info
Note:
Dirtybuild
oregg-info
dirs can cause problems: missing or stale files in the resulting dist or strange and confusing errors. Avoid having them around.
Then you should check that you got no packaging issues:
tox -e check
And then you can build the sdist
, and if possible, the bdist_wheel
too:
python setup.py clean --all sdist bdist_wheel
To make a release of the project on PyPI, assuming you got some distributions in dist/
, the most simple usage is:
twine upload --skip-existing dist/*.whl dist/*.gz dist/*.zip
In ZSH you can use this to upload everything in dist/
that ain't a linux-specific wheel (you may need setopt extended_glob
):
twine upload --skip-existing dist/*.(whl|gz|zip)~dist/*linux*.whl
For making and uploading manylinux1 wheels you can use this contraption:
docker run --rm -itv $(pwd):/code quay.io/pypa/manylinux1_x86_64 bash -c 'set -eux; cd code; rm -rf wheelhouse; for variant in /opt/python/*; do rm -rf dist build *.egg-info && $variant/bin/python setup.py clean --all bdist_wheel; auditwheel repair dist/*.whl; done; rm -rf dist build *.egg-info' twine upload --skip-existing wheelhouse/*.whl docker run --rm -itv $(pwd):/code quay.io/pypa/manylinux1_i686 bash -c 'set -eux; cd code; rm -rf wheelhouse; for variant in /opt/python/*; do rm -rf dist build *.egg-info && $variant/bin/python setup.py clean --all bdist_wheel; auditwheel repair dist/*.whl; done; rm -rf dist build *.egg-info' twine upload --skip-existing wheelhouse/*.whl
Note:
twine is a tool that you can use to securely upload your releases to PyPI.
You can still use the old python setup.py register sdist bdist_wheel upload
but it's not very secure - your PyPI
password will be sent over plaintext.
See CHANGELOG.rst.
There's no Makefile?
Sorry, noMakefile
yet. The Tox environments stand for whatever you'd have in aMakefile
.
Why does tox.ini
have a passenv = *
?
Tox 2.0 changes the way it runs subprocesses - it no longer passes all the environment variables by default. This causes all sorts of problems if you want to run/use any of these with Tox: SSH Agents, Browsers (for Selenium), Appengine SDK, VC Compiler and so on.
cookiecutter-pylibrary errs on the side of convenience here. You can always remove
passenv = *
if you like the strictness.
Why is the version stored in several files (pkg/__init__.py
, setup.py
, docs/conf.py
)?
We cannot use a metadata/version file [1] because this template is to be used with both distributions of packages (dirs with
__init__.py
) and modules (simple.py
files that go straigh insite-packages
). There's no good place for that extra file if you're distributing modules.But this isn't so bad - bumpversion manages the version string quite neatly.
[1] | Example, an __about__.py file. |
No way, this is the best. 😜
If you have criticism or suggestions please open up an Issue or Pull Request.