Skip to content

Commit

Permalink
Update template.
Browse files Browse the repository at this point in the history
  • Loading branch information
huxuan committed Dec 18, 2023
1 parent 045661e commit 3803503
Show file tree
Hide file tree
Showing 23 changed files with 117 additions and 616 deletions.
3 changes: 3 additions & 0 deletions template/.gitignore.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
[%- if project_name == "Serious Scaffold Python" %]
.copier-answers.yml
[%- endif %]
# TODO: Move `.pdm-python` out of custom section when upstream pull request merged.
# Reference: https://github.com/github/gitignore/pull/4279
.pdm-python
Pipfile
public
release-notes.md
Expand Down
30 changes: 4 additions & 26 deletions template/.pre-commit-config.yaml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,14 @@ repos:
- id: pretty-format-json
args:
- '--autofix'
- id: requirements-txt-fixer
args:
[%- if version_between("3.8", min_py, max_py) %]
- constraints/3.8.txt
[%- endif %]
[%- if version_between("3.9", min_py, max_py) %]
- constraints/3.9.txt
[%- endif %]
[%- if version_between("3.10", min_py, max_py) %]
- constraints/3.10.txt
[%- endif %]
[%- if version_between("3.11", min_py, max_py) %]
- constraints/3.11.txt
[%- endif %]
[%- if version_between("3.12", min_py, max_py) %]
- constraints/3.12.txt
[%- endif %]
- requirements.txt
- requirements/docs.txt
- requirements/lint.txt
- requirements/package.txt
- requirements/test.txt
- id: sort-simple-yaml
files: .pre-commit-config.yaml
- id: trailing-whitespace
- repo: local
hooks:
- id: mypy
name: mypy
entry: pipenv run python -m mypy
entry: pdm run python -m mypy
language: system
[%- if project_name == 'Serious Scaffold Python' %]
exclude: ^template/.*
Expand All @@ -62,23 +40,23 @@ repos:
require_serial: true
- id: ruff
name: ruff
entry: pipenv run python -m ruff check --force-exclude
entry: pdm run python -m ruff check --force-exclude
language: system
types_or:
- python
- pyi
require_serial: true
- id: ruff-format
name: ruff-format
entry: pipenv run python -m ruff format --force-exclude
entry: pdm run python -m ruff format --force-exclude
language: system
types_or:
- python
- pyi
require_serial: true
- id: toml-sort
name: toml-sort
entry: pipenv run toml-sort
entry: pdm run toml-sort
language: system
types:
- toml
Expand Down
60 changes: 25 additions & 35 deletions template/Makefile.jinja
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
[% from pathjoin("includes", "variable.jinja") import page_url with context -%]
.PHONY: clean deepclean install dev constraints mypy ruff ruff-format toml-sort lint pre-commit test-run test build upload docs-autobuild changelog docs-gen docs-mypy docs-coverage docs
.PHONY: clean deepclean install dev mypy ruff ruff-format toml-sort lint pre-commit test-run test build publish docs-autobuild changelog docs-gen docs-mypy docs-coverage docs

########################################################################################
# Variables
########################################################################################

# Determine whether to invoke pipenv based on CI environment variable and the availability of pipenv.
PIPRUN := $(shell [ "$$CI" != "true" ] && command -v pipenv > /dev/null 2>&1 && echo "pipenv run")

# Get the Python version in `major.minor` format, using the environment variable or the virtual environment if exists.
PYTHON_VERSION := $(shell echo $${PYTHON_VERSION:-$$(python -V 2>&1 | cut -d ' ' -f 2)} | cut -d '.' -f 1,2)

# Determine the constraints file based on the Python version.
CONSTRAINTS_FILE := constraints/$(PYTHON_VERSION).txt

# Documentation target directory, will be adapted to specific folder for readthedocs.
PUBLIC_DIR := $(shell [ "$$READTHEDOCS" = "True" ] && echo "$$READTHEDOCS_OUTPUT/html" || echo "public")

Expand All @@ -37,6 +31,7 @@ clean:
.pytest_cache \
.ruff_cache \
Pipfile* \
build \
coverage.xml \
dist \
release-notes.md
Expand All @@ -49,46 +44,41 @@ clean:
# Remove pre-commit hook, virtual environment alongside itermediate files.
deepclean: clean
if command -v pre-commit > /dev/null 2>&1; then pre-commit uninstall --hook-type pre-push; fi
if command -v pipenv >/dev/null 2>&1 && pipenv --venv >/dev/null 2>&1; then pipenv --rm; fi
if command -v pdm >/dev/null 2>&1 && pdm venv list | grep -q in-project ; then pdm venv remove --yes in-project >/dev/null 2>&1; fi

# Install the package in editable mode.
install:
$(PIPRUN) pip install -e . -c $(CONSTRAINTS_FILE)
pdm install --prod

# Install the package in editable mode with specific optional dependencies.
dev-%:
$(PIPRUN) pip install -e .[$*] -c $(CONSTRAINTS_FILE)
pdm install --group [$*]

# Prepare the development environment.
# Install the pacakge in editable mode with all optional dependencies and pre-commit hoook.
dev:
$(PIPRUN) pip install -e .[docs,lint,package,test] -c $(CONSTRAINTS_FILE)
pdm install
if [ "$(CI)" != "true" ] && command -v pre-commit > /dev/null 2>&1; then pre-commit install --hook-type pre-push; fi

# Generate constraints for current Python version.
constraints: deepclean
$(PIPRUN) --python $(PYTHON_VERSION) pip install --upgrade -e .[docs,lint,package,test]
$(PIPRUN) pip freeze --exclude-editable > $(CONSTRAINTS_FILE)

########################################################################################
# Lint and pre-commit
########################################################################################

# Check lint with mypy.
mypy:
$(PIPRUN) python -m mypy .
pdm run python -m mypy .

# Lint with ruff.
ruff:
$(PIPRUN) python -m ruff check .
pdm run python -m ruff check .

# Format with ruff.
ruff-format:
$(PIPRUN) python -m ruff format --check .
pdm run python -m ruff format --check .

# Check lint with toml-sort.
toml-sort:
$(PIPRUN) toml-sort --check pyproject.toml
pdm run toml-sort --check pyproject.toml

# Check lint with all linters.
lint: mypy ruff ruff-format toml-sort
Expand All @@ -103,33 +93,33 @@ pre-commit:

# Clean and run test with coverage.
test-run:
$(PIPRUN) python -m coverage erase
$(PIPRUN) python -m coverage run -m pytest
pdm run python -m coverage erase
pdm run python -m coverage run -m pytest

# Generate coverage report for terminal and xml.
test: test-run
$(PIPRUN) python -m coverage report
$(PIPRUN) python -m coverage xml
pdm run python -m coverage report
pdm run python -m coverage xml

########################################################################################
# Package
########################################################################################

# Build the package.
build:
$(PIPRUN) python -m build
pdm build

# Upload the package.
upload:
$(PIPRUN) python -m twine upload dist/*
# Publish the package.
publish:
pdm publish

########################################################################################
# Documentation
########################################################################################

# Generate documentation with auto build when changes happen.
docs-autobuild:
$(PIPRUN) python -m sphinx_autobuild docs $(PUBLIC_DIR) \
pdm run python -m sphinx_autobuild docs $(PUBLIC_DIR) \
--watch README.md \
--watch src

Expand All @@ -140,24 +130,24 @@ changelog:
echo "Existing Changelog found at '$(CHANGELOG_URL)', download for incremental generation."; \
wget -q -O $(CHANGELOG_PATH) $(CHANGELOG_URL); \
fi
$(PIPRUN) git-changelog -ETrio $(CHANGELOG_PATH) -c conventional -s build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test
pdm run git-changelog -ETrio $(CHANGELOG_PATH) -c conventional -s build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test

# Generate release notes from changelog.
release-notes:
@$(PIPRUN) git-changelog --input $(CHANGELOG_PATH) --release-notes
pdm run git-changelog --input $(CHANGELOG_PATH) --release-notes

# Build documentation only from src.
docs-gen:
$(PIPRUN) python -m sphinx.cmd.build docs $(PUBLIC_DIR)
pdm run python -m sphinx.cmd.build docs $(PUBLIC_DIR)

# Generate mypy reports.
docs-mypy: docs-gen
$(PIPRUN) python -m mypy src test --html-report $(PUBLIC_DIR)/reports/mypy
pdm run python -m mypy src test --html-report $(PUBLIC_DIR)/reports/mypy

# Generate html coverage reports with badge.
docs-coverage: test-run docs-gen
$(PIPRUN) python -m coverage html -d $(PUBLIC_DIR)/reports/coverage
$(PIPRUN) bash scripts/generate-coverage-badge.sh $(PUBLIC_DIR)/_static/badges
pdm run python -m coverage html -d $(PUBLIC_DIR)/reports/coverage
pdm run bash scripts/generate-coverage-badge.sh $(PUBLIC_DIR)/_static/badges

# Generate all documentation with reports.
docs: changelog docs-gen docs-mypy docs-coverage
Expand Down
7 changes: 3 additions & 4 deletions template/README.md.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ If you find this helpful, please consider [sponsorship](https://github.com/spons
## 🛠️ Features

- Project setup and template update with [`copier`](https://copier.readthedocs.io/).
- Manage [virtual environments](https://docs.python.org/3/glossary.html#term-virtual-environment) for development with [`pipenv`](https://pipenv.pypa.io/).
- Manage dependency with categorized [requirements](https://pip.pypa.io/en/stable/user_guide/#requirements-files) and [constraints](https://pip.pypa.io/en/stable/user_guide/#constraints-files).
- Manage dependencies and virtual environments with [`pdm`](https://pdm-project.org/).
- Automate Git hooks with [pre-commit hooks](https://github.com/pre-commit/pre-commit-hooks) and [local](https://pre-commit.com/#repository-local-hooks) linters.
- Lint with [`mypy`](http://www.mypy-lang.org/), [`ruff`](https://github.com/charliermarsh/ruff), and [`toml-sort`](https://github.com/pappasam/toml-sort).
- Test with [`pytest`](https://pytest.org/) and [`coverage`](https://coverage.readthedocs.io) for threshold and reports.
Expand All @@ -71,8 +70,8 @@ Certain system-level Python applications are needed and it is recommended to use
```bash
# Copier: Template rendering for projects.
pipx install copier
# Pipenv: Virtual environment and package manager for Python.
pipx install pipenv
# PDM: A modern Python package and dependency manager supporting the latest PEP standards.
pipx install pdm
# Pre-commit: Automates Git hooks for code quality checks.
pipx install pre-commit
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ updates:
schedule:
interval: weekly
- commit-message:
prefix: build(requirements)
prefix: build(dependencies)
directory: /
groups:
dev:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
[% from pathjoin("includes", "version_compare.jinja") import version_between -%]
name: CI
concurrency:
cancel-in-progress: true
group: {{ '${{ github.workflow }}-${{ github.ref }}' }}
jobs:
ci:
if: {{ '${{ !cancelled() && ! failure() }}' }}
needs: dependabot
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python {{ '${{ matrix.python-version }}' }}
uses: actions/setup-python@v5
- uses: pdm-project/setup-pdm@v3
with:
cache: pip
cache: true
python-version: {{ '${{ matrix.python-version }}' }}
- run: env | sort
- run: make dev
Expand All @@ -40,18 +39,16 @@ jobs:
[%- if project_name == "Serious Scaffold Python" %]
consistency:
if: {{ '${{ !cancelled() && ! failure() }}' }}
needs: dependabot
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Git
run: |
git config --global user.name github-actions
git config --global user.email [email protected]
- name: Set up Python
uses: actions/setup-python@v5
- uses: pdm-project/setup-pdm@v3
with:
cache: pip
cache: true
python-version: '{{ default_py }}'
- run: env | sort
- name: Install copier for template rendering using pipx
Expand All @@ -67,70 +64,6 @@ jobs:
- run: git status --porcelain
- run: test -z "$(git status --porcelain)"
[%- endif %]
dependabot:
if: {{ '${{ github.actor == \'dependabot[bot]\' && startsWith(github.head_ref, \'dependabot/pip/\') }}' }}
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: {{ '${{ github.head_ref }}' }}
- name: Set up Git
run: |
git config --global user.name github-actions
git config --global user.email [email protected]
- name: Set up Python with multiple versions.
uses: actions/setup-python@v5
with:
cache: pip
python-version: |
[%- if version_between("3.8", min_py, max_py) %]
3.8
[%- endif %]
[%- if version_between("3.9", min_py, max_py) %]
3.9
[%- endif %]
[%- if version_between("3.10", min_py, max_py) %]
3.10
[%- endif %]
[%- if version_between("3.11", min_py, max_py) %]
3.11
[%- endif %]
[%- if version_between("3.12", min_py, max_py) %]
3.12
[%- endif %]
- name: Install pipenv using pipx
run: pipx install pipenv
- name: Generate constraints for all supported Python versions
run: |
[%- if version_between("3.8", min_py, max_py) %]
CI= PYTHON_VERSION=3.8 make constraints
[%- endif %]
[%- if version_between("3.9", min_py, max_py) %]
CI= PYTHON_VERSION=3.9 make constraints
[%- endif %]
[%- if version_between("3.10", min_py, max_py) %]
CI= PYTHON_VERSION=3.10 make constraints
[%- endif %]
[%- if version_between("3.11", min_py, max_py) %]
CI= PYTHON_VERSION=3.11 make constraints
[%- endif %]
[%- if version_between("3.12", min_py, max_py) %]
CI= PYTHON_VERSION=3.12 make constraints
[%- endif %]
[%- if project_name == "Serious Scaffold Python" %]
- name: Sync template
run: cp -v constraints/* template/constraints/
[%- endif %]
- name: Push changes if applicable
run: |
if [[ -n `git status --porcelain` ]]; then
git commit -a -m "build: Update constraints for dependabot."
git push
fi
name: CI
on:
pull_request:
types:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
name: Lint pull request title
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -12,7 +13,6 @@ jobs:
echo 'Please refer to "https://www.conventionalcommits.org/"'
exit 1
fi
name: Lint pull request title
on:
pull_request:
types:
Expand Down
Loading

0 comments on commit 3803503

Please sign in to comment.