[PATCH 1/3] Add pylint testing

Brian C. Lane bcl at redhat.com
Fri May 9 00:50:32 UTC 2014


This adds pylint testing via make check, using the framework from
Anaconda. False positives can be added to
./tests/pylint/pylint-false-positives
---
 Makefile                            |   4 ++
 tests/lib/testlib.sh                |  37 ++++++++++
 tests/pylint/pylint-false-positives |   3 +
 tests/pylint/pylint-one.sh          |  32 +++++++++
 tests/pylint/runpylint.sh           | 140 ++++++++++++++++++++++++++++++++++++
 tests/testenv.sh                    |  19 +++++
 6 files changed, 235 insertions(+)
 create mode 100644 tests/lib/testlib.sh
 create mode 100644 tests/pylint/pylint-false-positives
 create mode 100755 tests/pylint/pylint-one.sh
 create mode 100755 tests/pylint/runpylint.sh
 create mode 100644 tests/testenv.sh

diff --git a/Makefile b/Makefile
index 654024d..7106c6b 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,10 @@ install: all
 	install -m 644 docs/lorax.1 $(DESTDIR)/$(mandir)/man1
 	install -m 644 docs/livemedia-creator.1 $(DESTDIR)/$(mandir)/man1
 
+check:
+	@echo "*** Running pylint ***"
+	./tests/pylint/runpylint.sh
+
 clean:
 	-rm -rf build src/pylorax/version.py
 
diff --git a/tests/lib/testlib.sh b/tests/lib/testlib.sh
new file mode 100644
index 0000000..896d884
--- /dev/null
+++ b/tests/lib/testlib.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Shell functions for use by anaconda tests
+#
+# Copyright (C) 2014  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Shea <dshea at redhat.com>
+
+# Print a list of files to test on stdout
+# Takes filter arguments identical to the find utility, for example
+# findtestfiles -name '*.py'. Note that pruning directories will not
+# work since find is passed a list of filenames as the path arguments.
+findtestfiles()
+{
+    # If the test is being run from a git work tree, use a list of all files
+    # known to git
+    if [ -d "${top_srcdir}/.git" ]; then
+        findpath=$(git ls-files -c "${top_srcdir}")
+    # Otherwise list everything under $top_srcdir
+    else
+        findpath="${top_srcdir} -type f"
+    fi
+
+    find $findpath "$@"
+}
diff --git a/tests/pylint/pylint-false-positives b/tests/pylint/pylint-false-positives
new file mode 100644
index 0000000..449a192
--- /dev/null
+++ b/tests/pylint/pylint-false-positives
@@ -0,0 +1,3 @@
+F0401 import-error Unable to import 'pylorax.version'
+E0611 no-name-in-module No name 'version' in module 'pylorax'
+E1101 no-member Module 'pylorax' has no 'version' member
diff --git a/tests/pylint/pylint-one.sh b/tests/pylint/pylint-one.sh
new file mode 100755
index 0000000..2c9a40c
--- /dev/null
+++ b/tests/pylint/pylint-one.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# $1 -- python source to run pylint on
+#
+
+if [ $# -lt 1 ]; then
+    # no source, just exit
+    exit 1
+fi
+
+file_suffix="$(eval echo \$$#|sed s?/?_?g)"
+
+pylint_output="$(pylint \
+    --msg-template='{path}:{line}: {msg_id} {symbol} {msg}' \
+    -r n --disable=C,R --rcfile=/dev/null \
+    --dummy-variables-rgx=_ \
+    --ignored-classes=Popen,TransactionSet \
+    --defining-attr-methods=__init__,_grabObjects,initialize,reset,start,setUp \
+    $DISABLED_WARN_OPTIONS \
+    $DISABLED_ERR_OPTIONS \
+    $NON_STRICT_OPTIONS "$@" 2>&1 | \
+    egrep -v -f "$FALSE_POSITIVES" \
+    )"
+
+# I0011 is the informational "Locally disabling ...." message
+if [ -n "$(echo "$pylint_output" | fgrep -v '************* Module ' |\
+          grep -v '^I0011:')" ]; then
+    # Replace the Module line with the actual filename
+    pylint_output="$(echo "$pylint_output" | sed "s|\* Module .*|* Module $(eval echo \$$#)|")"
+    echo "$pylint_output" > pylint-out_$file_suffix
+    touch "pylint-$file_suffix-failed"
+fi
diff --git a/tests/pylint/runpylint.sh b/tests/pylint/runpylint.sh
new file mode 100755
index 0000000..bd333e3
--- /dev/null
+++ b/tests/pylint/runpylint.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+# This script will check the project for any pylint warning and errors using a set
+# of options minimizing false positives, in combination with filtering of any
+# warning regularexpressions listed in pylint-false-positives.
+# 
+# If any warnings are found they will be stored in pylint-log and printed
+# to stdout and this script will exit with a status of 1, if no (non filtered)
+# warnings are found it exits with a status of 0
+
+# XDG_RUNTIME_DIR is "required" to be set, so make one up in case something
+# actually tries to do something with it
+if [ -z "$XDG_RUNTIME_DIR" ]; then
+    export XDG_RUNTIME_DIR="$(mktemp -d)"
+    trap "rm -rf \"$XDG_RUNTIME_DIR\"" EXIT
+fi
+
+# If $top_srcdir is set, assume this is being run from automake and we don't
+# need to keep a separate log
+export pylint_log=0
+if [ -z "$top_srcdir" ]; then
+    export pylint_log=1
+fi
+
+# Unset TERM so that things that use readline don't output terminal garbage
+unset TERM
+
+# Don't try to connect to the accessibility socket
+export NO_AT_BRIDGE=1
+
+# Force the GDK backend to X11. Otherwise if no display can be found, Gdk
+# tries every backend type, which includes "broadway," which prints an error
+# and keeps changing the content of said error.
+export GDK_BACKEND=x11
+
+# If $top_srcdir has not been set by automake, import the test environment
+if [ -z "$top_srcdir" ]; then
+    top_srcdir="$(dirname "$0")/../.."
+    . ${top_srcdir}/tests/testenv.sh
+fi
+
+. ${top_srcdir}/tests/lib/testlib.sh
+
+srcdir="${top_srcdir}/tests/pylint"
+builddir="${top_builddir}/tests/pylint"
+
+# Need to add the pylint module directory to PYTHONPATH as well.
+export PYTHONPATH="${PYTHONPATH}:${srcdir}"
+
+# Save analysis data in the pylint directory
+export PYLINTHOME="${builddir}/.pylint.d"
+[ -d "$PYLINTHOME" ] || mkdir "$PYLINTHOME"
+
+export FALSE_POSITIVES="${srcdir}"/pylint-false-positives
+
+# W0212 - Access to a protected member %s of a client class
+export NON_STRICT_OPTIONS="--disable=W0212"
+
+# E1103 - %s %r has no %r member (but some types could not be inferred)
+export DISABLED_ERR_OPTIONS="--disable=E1103"
+
+# W0110 - map/filter on lambda could be replaced by comprehension
+# W0123 - Use of eval
+# W0141 - Used builtin function %r
+# W0142 - Used * or ** magic
+# W0511 - Used when a warning note as FIXME or XXX is detected.
+# W0603 - Using the global statement
+# W0613 - Unused argument %r
+# W0614 - Unused import %s from wildcard import
+# I0011 - Locally disabling %s (i.e., pylint: disable)
+# I0012 - Locally enabling %s (i.e., pylint: enable)
+# I0013 - Ignoring entire file (i.e., pylint: skip-file)
+export DISABLED_WARN_OPTIONS="--disable=W0110,W0123,W0141,W0142,W0511,W0603,W0613,W0614,I0011,I0012,I0013"
+
+usage () {
+  echo "usage: `basename $0` [--strict] [--help] [files...]"
+  exit $1
+}
+
+# Separate the module parameters from the files list
+ARGS=
+FILES=
+while [ $# -gt 0 ]; do
+  case $1 in
+    --strict)
+      export NON_STRICT_OPTIONS=
+      ;;
+    --help)
+      usage 0
+      ;;
+    -*)
+      ARGS="$ARGS $1"
+      ;;
+    *)
+      FILES=$@
+      break
+  esac
+  shift
+done
+
+exit_status=0
+
+if [ -s pylint-log ]; then
+    rm pylint-log
+fi
+
+# run pylint one file / module at a time, otherwise it sometimes gets
+# confused
+if [ -z "$FILES" ]; then
+    # Test any file that either ends in .py or contains #!/usr/bin/python in
+    # the first line.  Scan everything except old_tests
+    FILES=$(findtestfiles \( -name '*.py' -o \
+                -exec /bin/sh -c "head -1 {} | grep -q '#!/usr/bin/python'" \; \) -print | \
+            egrep -v '(|/)old_tests/')
+fi
+
+num_cpus=$(getconf _NPROCESSORS_ONLN)
+# run pylint in paralel
+echo $FILES | xargs --max-procs=$num_cpus -n 1 "$srcdir"/pylint-one.sh $ARGS || exit 1
+
+for file in $(find -name 'pylint-out*'); do
+    cat "$file" >> pylint-log
+    rm "$file"
+done
+
+fails=$(find -name 'pylint*failed' -print -exec rm '{}' \;)
+if [ -z "$fails" ]; then
+    exit_status=0
+else
+    exit_status=1
+fi
+
+if [ -s pylint-log ]; then
+    echo "pylint reports the following issues:"
+    cat pylint-log
+elif [ -e pylint-log ]; then
+    rm pylint-log
+fi
+
+exit "$exit_status"
diff --git a/tests/testenv.sh b/tests/testenv.sh
new file mode 100644
index 0000000..4807442
--- /dev/null
+++ b/tests/testenv.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ -z "$top_srcdir" ]; then
+    echo "*** top_srcdir must be set"
+    exit 1
+fi
+
+# If no top_builddir is set, use top_srcdir
+: "${top_builddir:=$top_srcdir}"
+
+if [ -z "$PYTHONPATH" ]; then
+    PYTHONPATH="${top_builddir}/src/:${top_srcdir}/tests/lib"
+else
+    PYTHONPATH="${PYTHONPATH}:${top_srcdir}/src/:${top_srcdir}:${top_srcdir}/tests/lib"
+fi
+
+export PYTHONPATH
+export top_srcdir
+export top_builddir
-- 
1.9.0



More information about the anaconda-patches mailing list