diff --git a/.travis/check_pylint_diff b/.travis/check_pylint_diff index 6c206ce2133..48cb9044c74 100755 --- a/.travis/check_pylint_diff +++ b/.travis/check_pylint_diff @@ -3,13 +3,15 @@ # Licensed under http://www.apache.org/licenses/LICENSE-2.0 # Created By: miha@reciprocitylabs.com +set -o pipefail set -o nounset set -o errexit ARG1=${1:-} GIT_REPO="$(pwd)" -TMP_REPO="$(mktemp -d)" +TMP_REPO="$(mktemp -d pylint_diff.XXXXXXX)" SCRIPT=$(basename "$0") +PYLINT="$(command -v pylint 2>/dev/null || true)" trap 'status=$?; cd '$GIT_REPO'; rm -rf '$TMP_REPO'; exit $status' EXIT @@ -41,14 +43,18 @@ Given the commit tree: case $ARG1 in -h|--help) print_help ; esac +if [ ! "$PYLINT" ]; then + echo 'Error: pylint is required' + exit 3 +fi + # Make a local clone: prevents copying of objects # Handle shallow git clones -[ -f "$GIT_REPO/.git/shallow" ] && - is_shallow=true +is_shallow=$([ -f "$GIT_REPO/.git/shallow" ] && echo true || echo) if [ "$is_shallow" ]; then mv "$GIT_REPO/.git/shallow" "$GIT_REPO/.git/shallow-bak" fi -git clone -q --local "$GIT_REPO" "$TMP_REPO" 2>/dev/null +git clone -q --local --depth=50 "$GIT_REPO" "$TMP_REPO" 2>/dev/null if [ "$is_shallow" ]; then mv "$GIT_REPO/.git/shallow-bak" "$GIT_REPO/.git/shallow" cp "$GIT_REPO/.git/shallow" "$TMP_REPO/.git/shallow" @@ -95,8 +101,9 @@ checkout () n_lint_errors () { echo "$CHANGED_FILES" | - xargs pylint | - awk -F'[\\. ]' '/^Your code has been rated at /{ print $7 }' + xargs "$PYLINT" | + awk -F'[\\. ]' '/^Your code has been rated at /{ print $7 }' || + true } echo "Running pylint on current commit ($CURRENT_COMMIT)" @@ -107,7 +114,8 @@ checkout $PREVIOUS_COMMIT RESULT_PARENT=$( n_lint_errors ) checkout $CURRENT_COMMIT -echo "$CHANGED_FILES" | xargs pylint || true +echo +echo "$CHANGED_FILES" | xargs "$PYLINT" || true echo "Pylint results" echo "==============" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a74bf56abb8..b92cdb23d72 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,6 +55,11 @@ In addition, we add the following guidelines: reason) should have a `__name__ == '__main__'`-fenced code block that shows/tests the gist of that module in a user-friendly way. +Please ensure your commits pass code quality assurance by executing: + + pip install -r requirements-dev.txt + python setup.py lint + [PEP-8]: https://www.python.org/dev/peps/pep-0008/ [Google Python Style Guide]: https://google.github.io/styleguide/pyguide.html [Napoleon]: http://www.sphinx-doc.org/en/stable/ext/napoleon.html diff --git a/requirements-dev.txt b/requirements-dev.txt index 7fb0ea150a6..af85ddc217f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1 +1,2 @@ pylint +radon diff --git a/setup.py b/setup.py index 7820be437bb..8ea38fe055a 100755 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import os import sys import subprocess -from setuptools import find_packages +from setuptools import find_packages, Command if sys.version_info < (3, 4): sys.exit('Orange requires Python >= 3.4') @@ -182,6 +182,24 @@ def configuration(parent_package='', top_path=None): } +class LintCommand(Command): + """A setup.py lint subcommand developers can run locally.""" + description = "run code linter(s)" + user_options = [] + initialize_options = finalize_options = lambda self: None + + def run(self): + """Lint current branch compared to a reasonable master branch""" + sys.exit(subprocess.call(''' + set -eu + upstream=$(git rev-parse -q --verify upstream/master) + origin=$(git rev-parse -q --verify origin/master) + master=$(git rev-parse -q --verify master) + best_ancestor=$(git merge-base HEAD ${upstream:-${origin:-$master}}) + .travis/check_pylint_diff $best_ancestor + ''', shell=True, cwd=os.path.dirname(os.path.abspath(__file__)))) + + def setup_package(): write_version_py() setup( @@ -201,6 +219,9 @@ def setup_package(): entry_points=ENTRY_POINTS, zip_safe=False, test_suite='Orange.tests.test_suite', + cmdclass={ + 'lint': LintCommand, + }, ) if __name__ == '__main__':