diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3537c50 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[Makefile] +indent_style = tab + +[*.{py,cfg,ini,toml,yaml,yml,md,sh}] +indent_style = space +indent_size = 4 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4f8a87a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "pre-commit" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5365571..1b1d4ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,13 +6,16 @@ on: branches: - main +permissions: + contents: read + jobs: test: name: Build (Python ${{ matrix.python }}) runs-on: ubuntu-latest strategy: matrix: - python: ['3.9', '3.10', '3.11'] + python: ['3.9', '3.10', '3.11', '3.12', '3.13'] env: TERM: xterm-256color @@ -22,18 +25,15 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v5 + - name: Set up uv + uses: astral-sh/setup-uv@v6 with: + enable-cache: true python-version: ${{ matrix.python }} - - name: Install Dependencies - run: | - make dev-deps - - name: Build Packages run: | - make build + uv run make build - name: Upload Packages uses: actions/upload-artifact@v4 diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index f3c1a2d..b8e5da8 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -6,6 +6,9 @@ on: branches: - main +permissions: + contents: read + jobs: test: name: Install (Python ${{ matrix.python }}) @@ -14,7 +17,7 @@ jobs: TERM: xterm-256color strategy: matrix: - python: ['3.9', '3.10', '3.11'] + python: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - name: Checkout Code diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 2e166c0..903a649 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -6,6 +6,9 @@ on: branches: - main +permissions: + contents: read + jobs: test: name: Linting & Spelling @@ -17,23 +20,20 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - - name: Set up Python '3,11' - uses: actions/setup-python@v5 + - name: Set up uv + uses: astral-sh/setup-uv@v6 with: + enable-cache: true python-version: '3.11' - - name: Install Dependencies - run: | - make dev-deps - - name: Run Quality Assurance run: | - make qa + uv run make qa - name: Run Code Checks run: | - make check + uv run make check - - name: Run Bash Code Checks + - name: Run Pre-Commit run: | - make shellcheck + uv run pre-commit run --all-files diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e29cb9..8e4fb06 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,6 +6,9 @@ on: branches: - main +permissions: + contents: read + jobs: test: name: Test (Python ${{ matrix.python }}) @@ -14,30 +17,25 @@ jobs: TERM: xterm-256color strategy: matrix: - python: ['3.9', '3.10', '3.11'] + python: ['3.9', '3.10', '3.11', '3.12', '3.13'] steps: - name: Checkout Code uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v5 + - name: Set up uv + uses: astral-sh/setup-uv@v6 with: + enable-cache: true python-version: ${{ matrix.python }} - - name: Install Dependencies - run: | - make dev-deps - - name: Run Tests run: | - make pytest + uv run make pytest - name: Coverage if: ${{ matrix.python == '3.9' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - python -m pip install coveralls - coveralls --service=github - + uvx coveralls --service=github diff --git a/.gitignore b/.gitignore index fa45562..c673bb6 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ library/debian/ .coverage .pytest_cache .tox +.venv +uv.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..53210a8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: mixed-line-ending + args: ['--fix=lf'] + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.20 + hooks: + - id: ruff-check + args: ['--fix'] + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + additional_dependencies: ['tomli'] + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.10.0.1 + hooks: + - id: shellcheck diff --git a/.stickler.yml b/.stickler.yml deleted file mode 100644 index 2466815..0000000 --- a/.stickler.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -linters: - flake8: - python: 3 - max-line-length: 160 diff --git a/Makefile b/Makefile index 56cf0df..29700a2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ LIBRARY_NAME := $(shell hatch project metadata name 2> /dev/null) LIBRARY_VERSION := $(shell hatch version 2> /dev/null) -.PHONY: usage install uninstall check pytest qa build-deps check tag wheel sdist clean dist testdeploy deploy +.PHONY: usage version install uninstall dev-deps check pre-commit qa pytest nopost tag build clean testdeploy deploy usage: ifdef LIBRARY_NAME @echo "Library: ${LIBRARY_NAME}" @@ -13,8 +13,9 @@ endif @echo "install: install the library locally from source" @echo "uninstall: uninstall the local library" @echo "dev-deps: install Python dev dependencies" - @echo "check: perform basic integrity checks on the codebase" - @echo "qa: run linting and package QA" + @echo "check: verify CHANGELOG.md has an entry for the current version" + @echo "qa: run package QA (check-manifest, build, twine)" + @echo "pre-commit: run pre-commit hooks (lint, whitespace) on all files" @echo "pytest: run Python test fixtures" @echo "clean: clean Python build and dist directories" @echo "build: build Python distribution files" @@ -32,14 +33,20 @@ uninstall: ./uninstall.sh dev-deps: - python3 -m pip install -r requirements-dev.txt - sudo apt install dos2unix shellcheck + python3 -m pip install --group dev + pre-commit install check: - @bash check.sh + @LIBRARY_VERSION=`hatch version | awk -F '.' '{print $$1"."$$2"."$$3}'`; \ + if grep -q "^$$LIBRARY_VERSION" CHANGELOG.md; then \ + echo "Changes found for version $$LIBRARY_VERSION."; \ + else \ + echo "Changes missing for version $$LIBRARY_VERSION! Please update CHANGELOG.md."; \ + exit 1; \ + fi -shellcheck: - shellcheck *.sh +pre-commit: + pre-commit run --all-files qa: tox -e qa @@ -48,13 +55,17 @@ pytest: tox -e py nopost: - @bash check.sh --nopost + @POST_VERSION=`hatch version | awk -F '.' '{print $$4}'`; \ + if [ -n "$$POST_VERSION" ]; then \ + echo "Found .$$POST_VERSION on library version; only use these for testpypi releases."; \ + exit 1; \ + fi tag: version git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" build: check - @hatch build + uv build clean: -rm -r dist diff --git a/README.md b/README.md index 4652f1b..b457c12 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ product description goes here # Installing -We'd recommend using this library with Raspberry Pi OS Bookworm or later. It requires Python ≥3.7. +We'd recommend using this library with Raspberry Pi OS Bookworm or later. It requires Python ≥3.9. ## Full install (recommended): diff --git a/check.sh b/check.sh deleted file mode 100755 index 3dfe6f1..0000000 --- a/check.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash - -# This script handles some basic QA checks on the source - -NOPOST=$1 -LIBRARY_NAME=$(hatch project metadata name) -LIBRARY_VERSION=$(hatch version | awk -F "." '{print $1"."$2"."$3}') -POST_VERSION=$(hatch version | awk -F "." '{print substr($4,0,length($4))}') -TERM=${TERM:="xterm-256color"} - -success() { - echo -e "$(tput setaf 2)$1$(tput sgr0)" -} - -inform() { - echo -e "$(tput setaf 6)$1$(tput sgr0)" -} - -warning() { - echo -e "$(tput setaf 1)$1$(tput sgr0)" -} - -while [[ $# -gt 0 ]]; do - K="$1" - case $K in - -p|--nopost) - NOPOST=true - shift - ;; - *) - if [[ $1 == -* ]]; then - printf "Unrecognised option: %s\n" "$1"; - exit 1 - fi - POSITIONAL_ARGS+=("$1") - shift - esac -done - -inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n" - -inform "Checking for trailing whitespace..." -if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist -exclude-dir=.venv --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then - warning "Trailing whitespace found!" - exit 1 -else - success "No trailing whitespace found." -fi -printf "\n" - -inform "Checking for DOS line-endings..." -if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox -exclude-dir=.venv --exclude-dir=.git --exclude=Makefile; then - warning "DOS line-endings found!" - exit 1 -else - success "No DOS line-endings found." -fi -printf "\n" - -inform "Checking CHANGELOG.md..." -if ! grep "^${LIBRARY_VERSION}" CHANGELOG.md > /dev/null 2>&1; then - warning "Changes missing for version ${LIBRARY_VERSION}! Please update CHANGELOG.md." - exit 1 -else - success "Changes found for version ${LIBRARY_VERSION}." -fi -printf "\n" - -inform "Checking for git tag ${LIBRARY_VERSION}..." -if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then - warning "Missing git tag for version ${LIBRARY_VERSION}" -fi -printf "\n" - -if [[ $NOPOST ]]; then - inform "Checking for .postN on library version..." - if [[ "$POST_VERSION" != "" ]]; then - warning "Found .$POST_VERSION on library version." - inform "Please only use these for testpypi releases." - exit 1 - else - success "OK" - fi -fi diff --git a/pyproject.toml b/pyproject.toml index b477b15..f23de4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "PROJECT_NAME" dynamic = ["version", "readme", "optional-dependencies"] description = "__DESCRIPTION__" license = {file = "LICENSE"} -requires-python = ">= 3.7" +requires-python = ">= 3.9" authors = [ { name = "Philip Howard", email = "phil@pimoroni.com" }, ] @@ -24,11 +24,11 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development", "Topic :: Software Development :: Libraries", @@ -43,15 +43,26 @@ example-depends = ["requirements-examples.txt"] GitHub = "https://www.github.com/pimoroni/PROJECT_NAME-python" Homepage = "https://www.pimoroni.com" +[dependency-groups] +dev = [ + "check-manifest", + "ruff", + "codespell", + "pre-commit", + "twine", + "hatch", + "hatch-fancy-pypi-readme", + "hatch-requirements-txt", + "tox", + "pdoc", +] + [tool.hatch.version] path = "PROJECT_NAME/__init__.py" [tool.hatch.build] include = [ "PROJECT_NAME", - "README.md", - "CHANGELOG.md", - "LICENSE", "requirements-examples.txt" ] @@ -61,7 +72,8 @@ include = [ ] exclude = [ ".*", - "dist" + "dist", + "uv.lock" ] [tool.hatch.metadata.hooks.fancy-pypi-readme] @@ -83,24 +95,23 @@ exclude = [ ] line-length = 200 +[tool.ruff.lint] +extend-select = ["I"] + [tool.codespell] skip = """ ./.tox,\ +./.venv,\ ./.egg,\ ./.git,\ ./__pycache__,\ ./build,\ -./dist.\ +./dist\ """ -[tool.isort] -line_length = 200 - [tool.check-manifest] ignore = [ - '.stickler.yml', 'boilerplate.md', - 'check.sh', 'install.sh', 'uninstall.sh', 'Makefile', @@ -108,7 +119,8 @@ ignore = [ 'tests/*', 'examples/*', '.coveragerc', - 'requirements-dev.txt' + '.editorconfig', + '.pre-commit-config.yaml' ] [tool.pimoroni] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index d392e8f..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,10 +0,0 @@ -check-manifest -ruff -codespell -isort -twine -hatch -hatch-fancy-pypi-readme -hatch-requirements-txt -tox -pdoc diff --git a/tox.ini b/tox.ini index 2b6d87b..e9042d6 100644 --- a/tox.ini +++ b/tox.ini @@ -19,9 +19,5 @@ commands = check-manifest python -m build --no-isolation python -m twine check dist/* - isort --check . - ruff check . - codespell . -deps = - -r{toxinidir}/requirements-dev.txt - +dependency_groups = + dev