From 5533c57c8ca219697e71c2ac92b2cdd6ad312c77 Mon Sep 17 00:00:00 2001 From: Bruno Rousseau Date: Sat, 24 Feb 2024 06:26:45 -0500 Subject: [PATCH 1/3] New pre-commit script This script only checks files that are staged in git. --- README.md | 3 ++ hooks/pre-commit_staged | 69 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100755 hooks/pre-commit_staged diff --git a/README.md b/README.md index 6a77c6d7..0e7cece3 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ These hooks will: cd .git/hooks/ && ln -s ../../hooks/pre-commit . +Alternatively, to only lint files that have been staged in git, use + cd .git/hooks/ && ln -s ../../hooks/pre-commit_staged pre-commit + ### Setup Continuous Integration Continuous integration will run the following: diff --git a/hooks/pre-commit_staged b/hooks/pre-commit_staged new file mode 100755 index 00000000..3c5d3424 --- /dev/null +++ b/hooks/pre-commit_staged @@ -0,0 +1,69 @@ +#!/bin/sh + +# exit at the first error +set -e + +# flake8 linting + +# Only extract the python files that git has staged; no need to lint WIP files that are not staged. + +# We'll use files to use intermediate results; it's easier to use grep on files. +staged_file_name="staged_file.tmp" +python_staged_file_name="python_staged_file.tmp" + +git diff --name-only --cached > $staged_file_name + +# Grep has the following behavior: +# the exit code is 0 if there is a match +# the exit code is 1 if there is no match +# the exit code is >1 if there is an error +# +# No match is a legitimate result, but the exit code of 1 is interpreted as an error by bash. +# To work around this issue, we'll use +# grep [...] || [[ $? == 1]] +# which has an exit code of 0 if there is a match or if there are no match. + +grep '.*py$' $staged_file_name > $python_staged_file_name || [[ $? == 1 ]] +python_staged_files=`cat $python_staged_file_name` + +python_non_tests_staged_files=`grep -v '^tests' $python_staged_file_name || [[ $? == 1 ]]` + +rm $python_staged_file_name $staged_file_name + + +if [ -z "${python_staged_files}" ]; then + echo "No python file to lint" +else + flake8 --ignore D,W503 --max-line-length=120 $python_staged_files # Check everything but docstrings +fi + +if [ -z "${python_non_tests_staged_files}" ]; then + echo "No non-test python file to docstring lint" +else + flake8 --select D --ignore D104,D100,D401 --docstring-convention google --exclude tests/ $python_non_tests_staged_files # Check only the docstrings +fi + + +# Raise error if any staged notebooks contain outputs +GITDIR=$(git rev-parse --show-toplevel) # Full path to git working directory +IPYNB_FILES=$(git diff --name-only --cached | grep .ipynb || true) # Find all committed notebooks +if [ "$IPYNB_FILES" != "" ] && [ -z $ALLOW_IPYNB ]; then + for f in $IPYNB_FILES + do + DIFF=$(jupyter nbconvert --log-level ERROR --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --to notebook --stdout $GITDIR/$f | diff $GITDIR/$f - || :) + if [ "$DIFF" != "" ]; then + echo " + The notebook $GITDIR/$f contains outputs. + Remove them all before committing. + ***Hint*** use the command: + + jupyter nbconvert --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --to notebook --inplace $GITDIR/$f + + To ignore this error, and add a notebook with outputs, use: + + export ALLOW_IPYNB=1 + " + exit 1 + fi + done +fi From 6a5e73393d1ac1b4f019a76e1aed9dd3058516ee Mon Sep 17 00:00:00 2001 From: Bruno Rousseau Date: Sat, 24 Feb 2024 06:42:21 -0500 Subject: [PATCH 2/3] use isort --- hooks/pre-commit_staged | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooks/pre-commit_staged b/hooks/pre-commit_staged index 3c5d3424..d57452d1 100755 --- a/hooks/pre-commit_staged +++ b/hooks/pre-commit_staged @@ -35,12 +35,14 @@ if [ -z "${python_staged_files}" ]; then echo "No python file to lint" else flake8 --ignore D,W503 --max-line-length=120 $python_staged_files # Check everything but docstrings + isort --check $python_staged_files # Check imports fi if [ -z "${python_non_tests_staged_files}" ]; then echo "No non-test python file to docstring lint" else flake8 --select D --ignore D104,D100,D401 --docstring-convention google --exclude tests/ $python_non_tests_staged_files # Check only the docstrings + isort --check $python_non_tests_staged_files # Check imports fi From b4e1003ac42687f0c3057924066d27e083e772f8 Mon Sep 17 00:00:00 2001 From: Bruno Rousseau Date: Sat, 24 Feb 2024 06:44:17 -0500 Subject: [PATCH 3/3] Add isort as a dependency, for pre-commit hook. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 9f1017c0..0db43ec0 100644 --- a/setup.py +++ b/setup.py @@ -8,6 +8,7 @@ install_requires=[ 'flake8==4.0.1', 'flake8-docstrings==1.6.0', + 'isort==5.13.2', 'gitpython==3.1.27', 'jupyter==1.0.0', 'jinja2==3.1.2',