cookiecutter-flit

A Cookiecutter template for a Flit package
git clone git://git.danielmoch.com/cookiecutter-flit.git
Log | Files | Refs | LICENSE

commit caf81585936b44c98d00dfaeddb3359214e0aefd
parent 168faf22f5eddb7ee08e61387d55c9f70cad1ee2
Author: Daniel Moch <daniel@danielmoch.com>
Date:   Sun, 26 Aug 2018 20:32:45 -0400

Improvements and lessons-learned

Lessons learned (from hookmeup):
1. Use a Makefile for as many commands as possible
2. Force all dependency management through Pipenv
3. On that note, always use Pipenv
4. Add support for Tox, Travis CI, and Coveralls

Diffstat:
Mcookiecutter.json | 1-
Mhooks/post_gen_project.py | 18+++++++++++-------
Mhooks/pre_gen_project.py | 8++++----
A{{cookiecutter.project_slug}}/.travis.yml | 41+++++++++++++++++++++++++++++++++++++++++
M{{cookiecutter.project_slug}}/Makefile | 40+++++++++++++++++++++-------------------
M{{cookiecutter.project_slug}}/Pipfile | 8+++-----
A{{cookiecutter.project_slug}}/tox.ini | 29+++++++++++++++++++++++++++++
7 files changed, 109 insertions(+), 36 deletions(-)

diff --git a/cookiecutter.json b/cookiecutter.json @@ -8,7 +8,6 @@ "project_short_description": "Flit Boilerplate contains all the boilerplate you need to create a Python Flit package.", "pypi_username": "{{ cookiecutter.github_username }}", "version": "0.1.0", - "use_pipenv": "y", "script_entrypoint": "y", "open_source_license": ["MIT license", "BSD license", "ISC license", "Apache Software License 2.0", "GNU General Public License v3", "Not open source"] } diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py @@ -1,21 +1,25 @@ -#!/usr/bin/env python3 +# -*- encoding: utf-8 *-* +"""Hook to run after template is created""" import os import subprocess +from subprocess import CalledProcessError PROJECT_DIRECTORY = os.path.realpath(os.path.curdir) - def remove_file(filepath): + """Remove a file from the generated template""" os.remove(os.path.join(PROJECT_DIRECTORY, filepath)) - if __name__ == '__main__': - if 'Not open source' == '{{ cookiecutter.open_source_license }}': remove_file('LICENSE') - if '{{ cookiecutter.use_pipenv }}' == 'n': - remove_file('Pipfile') - else: + try: + subprocess.run( + ['which', + 'pipenv'], + stdout=subprocess.DEVNULL).check_returncode() subprocess.run(['pipenv', 'lock', '--dev']) subprocess.run(['pipenv', 'sync', '--dev']) + except CalledProcessError: + print('pipenv not installed, or not available on PATH') diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py @@ -1,13 +1,14 @@ +# -*- encoding: utf-8 -*- +"""Hook to run before the template is generated""" import re import sys - MODULE_REGEX = r'^[_a-zA-Z][_a-zA-Z0-9]+$' -module_name = '{{ cookiecutter.project_slug}}' +module_name = '{{ cookiecutter.project_slug }}' if not re.match(MODULE_REGEX, module_name): print('ERROR: The project slug (%s) is not a valid Python module name. Please do not use a - and use _ instead' % module_name) #Exit to cancel project - sys.exit(1)- \ No newline at end of file + sys.exit(1) diff --git a/{{cookiecutter.project_slug}}/.travis.yml b/{{cookiecutter.project_slug}}/.travis.yml @@ -0,0 +1,41 @@ +# https://travis-ci.org/djmoch/{{ cookiecutter.project_slug }} +language: python + +matrix: + fast_finish: true + +.mixins: +- &xenial-mixin + dist: xenial + sudo: true + addons: + apt: + packages: + - libgnutls-dev + +env: + - PIPENV_HIDE_EMOJIS=1 PIPENV_NO_INHERIT=1 + +install: + - pip install pipenv python-coveralls + - make test-install + +jobs: + include: + - stage: test + script: make test + python: 3.5 + - stage: test + script: make test + python: 3.6 + - stage: test + script: make test + <<: *xenial-mixin + python: 3.7 + - stage: lint + script: make lint + python: 3.6 + - stage: coverage + script: make coverage + after_success: coveralls + python: 3.5 diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile @@ -1,4 +1,4 @@ -.PHONY: clean clean-test clean-pyc clean-build help +.PHONY: clean clean-test clean-pyc clean-build help lint coverage coverage-html release dist install run debug .DEFAULT_GOAL := help define BROWSER_PYSCRIPT @@ -26,13 +26,6 @@ export PRINT_HELP_PYSCRIPT BROWSER := python -c "$$BROWSER_PYSCRIPT" -# Comment out the following line to run outside of Pipenv -{%- if cookiecutter.use_pipenv == 'y' %} -PIPENV := pipenv run -{%- else %} -# PIPENV := pipenv run -{%- endif %} - help: @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) @@ -55,28 +48,37 @@ clean-test: ## remove test and coverage artifacts rm -f .coverage rm -fr htmlcov/ rm -fr .pytest_cache + rm -fr .tox lint: ## check style with pylint - $(PIPENV) pylint --rcfile tests/pylintrc {{ cookiecutter.project_slug }} tests + pipenv run pylint --rcfile tests/pylintrc {{ cookiecutter.project_slug }} tests --disable=parse-error test: ## run tests quickly with the default Python - $(PIPENV) python -m pytest + pipenv run python -m pytest + +test-install: ## install dependenices from Pipfile (for tox / CI builds) + pipenv --bare install --dev --skip-lock coverage: ## check code coverage quickly with the default Python - $(PIPENV) python -m pytest - $(PIPENV) coverage report -m - $(PIPENV) coverage html + pipenv run python -m pytest --cov={{ cookiecutter.project_slug }} --cov-config tests/coveragerc + pipenv run coverage report -m + +coverage-html: coverage ## generate an HTML report and open in browser + pipenv run coverage html $(BROWSER) htmlcov/index.html release: dist ## package and upload a release - $(PIPENV) flit publish + pipenv run flit publish -dist: clean ## builds source and wheel package - $(PIPENV) flit build +dist: ## builds source and wheel package + pipenv run flit build ls -l dist -install: clean ## install the package to the active Python's site-packages - $(PIPENV) flit install +install: ## install the package to the active Python's site-packages + pipenv run flit install + +run: install ## run the package from site-packages + pipenv run {{ cookiecutter.project_slug }} debug: install ## debug the package from site packages - $(PIPENV) pudb3 `$(PIPENV) which {{ cookiecutter.project_slug }}` install + pipenv run pudb3 `pipenv run which {{ cookiecutter.project_slug }}` diff --git a/{{cookiecutter.project_slug}}/Pipfile b/{{cookiecutter.project_slug}}/Pipfile @@ -4,12 +4,10 @@ verify_ssl = true name = "pypi" [packages] +flit = "*" [dev-packages] -pytest = "<3.7.0" +pytest = "*" pytest-cov = "*" -pytest-pylint = "*" +pylint = "*" pudb = "*" - -[requires] -python_version = "3.7" diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini @@ -0,0 +1,29 @@ +[tox] +envlist = py35, py36, py37, pylint, coverage +skipsdist = True + +[testenv:pylint] +deps = pylint +whitelist_externals = make +commands = make lint + +[testenv:coverage] +deps = pipenv +setenv = + PIPENV_NO_INHERIT = 1 + PIPENV_HIDE_EMOJIS = 1 +whitelist_externals = make +commands = + make test-install + make coverage + +[testenv] +deps = pipenv +setenv = + PIPENV_NO_INHERIT = 1 + PIPENV_HIDE_EMOJIS = 1 +whitelist_externals = make +commands = + make test-install + make install + make test