debian/0002775000000000000000000000000012143266243007175 5ustar debian/regression.sh0000775000000000000000000000030612143254543011711 0ustar #!/bin/sh # Properly invoke the upstream unit tests. # This is intended to be run from the same directory as dpkg-buildpackage. sh ./test_check.sh PYTHONPATH=`pwd`:$PYTHONPATH python ./test/main.py debian/pychecker.dirs0000664000000000000000000000003312143254543012027 0ustar usr/bin usr/share/pyshared debian/wrapper0000664000000000000000000000212112143254543010572 0ustar #!/bin/sh # We need to execute checker.py rather than simply importing it. However, # since pychecker is not a private package, we don't know exactly where it will # be located. So, we run a little Python script first to find the correct # location, and then execute it from there. # # Expect CHECKER_PATH to be something like: # # /usr/share/pyshared/pychecker/checker.py # # Its actual location will depend on how dh_python2 is implemented. # # This script also supports the use of $PYTHONVER as a way to select which # version of Python will be used to execute pychecker. This will only work for # versions of Python supported by dh_python2, but it's better than nothing. PYTHON="/usr/bin/python${PYTHONVER}" CHECKER_PATH=`${PYTHON} -c "from imp import find_module; print find_module('pychecker/checker')[1]"` if [ ! -n "${CHECKER_PATH}" ]; then echo "Unable to find checker.py on Python's module path." exit 1 fi if [ ! -f "${CHECKER_PATH}" ]; then echo "Found checker.py as [${CHECKER_PATH}], but it does not seem to exist." exit 1 fi exec "${PYTHON}" "${CHECKER_PATH}" "$@" debian/pychecker.10000664000000000000000000002112712143254543011235 0ustar .TH PYCHECKER "1" "Jan 2011" "pychecker 0.8.19" "User Commands" .SH NAME \fBpychecker \fP- program to check python scripts for common mistakes .SH SYNOPSIS .nf .fam C \fBpychecker\fP [\fIoptions\fP] files\.\.\. .fam T .fi .SH DESCRIPTION This manual page documents briefly the \fBpychecker\fP command. It was written for the Debian GNU/Linux distribution because the original program does not have a manual page. .PP \fBpychecker\fP is a program that finds common bugs in python source code. It finds problems that are typically caught by a compiler for less dynamic languages, like C and C++. Because of the dynamic nature of python, some warnings may be incorrect; however, spurious warnings should be fairly infrequent. .PP \fBpychecker\fP works in a combination of ways. First, it imports each module. If there is an import error, the module cannot be processed. The import provides some basic information about the module. The code for each function, class, and method is checked for possible problems. .SH CHOICE OF PYTHON VERSION .PP By default, the /usr/bin/pychecker script executes pychecker using the default Python interpreter in /usr/bin/python. Some users may want to run pychecker with a different Python interpreter. To accommodate this, the /usr/bin/pychecker script supports the use of $PYTHONVER on the command\-line, i.e. .TP .B PYTHONVER=2.3 pychecker file.py .PP If $PYTHONVER is set, /usr/bin/pychecker will attempt to execute pychecker using /usr/bin/python$PYTHONVER instead of /usr/bin/python. .PP Note, however, that this will only work for versions of the python interpreter supported by the current Debian Python infrastructure, not for any arbitrary Python interpreter installed in /usr/bin. .SH OPTIONS Long \fIoptions\fP can be preceded with no\- to turn off (e.g., no\-namedargs). Default settings are indicated by [brackets] .PP .SS "Major Options:" .TP \fB\-\-only\fR only warn about files passed on the command line [off] .TP \fB\-e\fR, \fB\-\-level\fR the maximum error level of warnings to be displayed .TP \-#, \fB\-\-limit\fR the maximum number of warnings to be displayed [10] .TP \fB\-F\fR, \fB\-\-config\fR specify .pycheckrc file to use .TP \fB\-\-quixote\fR support Quixote's PTL modules .TP \fB\-\-evil\fR list of evil C extensions that crash the interpreter [[]] .SS "Error Control:" .TP \fB\-i\fR, \fB\-\-import\fR unused imports [on] .TP \fB\-k\fR, \fB\-\-pkgimport\fR unused imports from __init__.py [on] .HP \fB\-M\fR, \fB\-\-reimportself\fR module imports itself [on] .TP \fB\-X\fR, \fB\-\-reimport\fR reimporting a module [on] .TP \fB\-x\fR, \fB\-\-miximport\fR module does import and from ... import [on] .TP \fB\-l\fR, \fB\-\-local\fR unused local variables, except tuples [on] .TP \fB\-t\fR, \fB\-\-tuple\fR all unused local variables, including tuples [off] .TP \fB\-9\fR, \fB\-\-members\fR all unused class data members [off] .TP \fB\-v\fR, \fB\-\-var\fR all unused module variables [off] .TP \fB\-p\fR, \fB\-\-privatevar\fR unused private module variables [on] .TP \fB\-g\fR, \fB\-\-allglobals\fR report each occurrence of global warnings [off] .TP \fB\-n\fR, \fB\-\-namedargs\fR functions called with named arguments (like keywords) [off] .TP \fB\-a\fR, \fB\-\-initattr\fR Attributes (members) must be defined in __init__() [off] .HP \fB\-I\fR, \fB\-\-initsubclass\fR Subclass.__init__() not defined [off] .TP \fB\-u\fR, \fB\-\-callinit\fR Baseclass.__init__() not called [on] .TP \fB\-0\fR, \fB\-\-abstract\fR Subclass needs to override methods that only throw exceptions [on] .TP \fB\-N\fR, \fB\-\-initreturn\fR Return None from __init__() [on] .TP \fB\-8\fR, \fB\-\-unreachable\fR unreachable code [off] .TP \fB\-2\fR, \fB\-\-constCond\fR a constant is used in a conditional statement [on] .TP \fB\-1\fR, \fB\-\-constant1\fR 1 is used in a conditional statement (if 1: or while 1:) [off] .TP \fB\-\-stringiter\fR check if iterating over a string [on] .TP \fB\-\-stringfind\fR check improper use of string.find() [on] .TP \fB\-A\fR, \fB\-\-callattr\fR Calling data members as functions [off] .TP \fB\-y\fR, \fB\-\-classattr\fR class attribute does not exist [on] .TP \fB\-S\fR, \fB\-\-self\fR First argument to methods [self] .HP \fB\-\-classmethodargs\fR First argument to classmethods [['cls', 'klass']] .TP \fB\-T\fR, \fB\-\-argsused\fR unused method/function arguments [on] .TP \fB\-z\fR, \fB\-\-varargsused\fR unused method/function variable arguments [on] .TP \fB\-G\fR, \fB\-\-selfused\fR ignore if self is unused in methods [off] .TP \fB\-o\fR, \fB\-\-override\fR check if overridden methods have the same signature [on] .TP \fB\-\-special\fR check if __special__ methods exist and have the correct signature [on] .TP \fB\-U\fR, \fB\-\-reuseattr\fR check if function/class/method names are reused [on] .TP \fB\-Y\fR, \fB\-\-positive\fR check if using unary positive (+) which is usually meaningless [on] .TP \fB\-j\fR, \fB\-\-moddefvalue\fR check if modify (call method) on a parameter that has a default value [on] .TP \fB\-\-changetypes\fR check if variables are set to different types [off] .TP \fB\-\-unpack\fR check if unpacking a non\-sequence [on] .TP \fB\-\-unpacklen\fR check if unpacking sequence with the wrong length [on] .TP \fB\-\-badexcept\fR check if raising or catching bad exceptions [on] .TP \fB\-4\fR, \fB\-\-noeffect\fR check if statement appears to have no effect [on] .TP \fB\-\-modulo1\fR check if using (expr % 1), it has no effect on integers and strings [on] .TP \fB\-\-isliteral\fR check if using (expr is const\-literal), doesn't always work on integers and strings [on] .SS "Possible Errors:" .HP \fB\-r\fR, \fB\-\-returnvalues\fR check consistent return values [on] .HP \fB\-C\fR, \fB\-\-implicitreturns\fR check if using implict and explicit return values [on] .TP \fB\-O\fR, \fB\-\-objattrs\fR check that attributes of objects exist [on] .TP \fB\-7\fR, \fB\-\-slots\fR various warnings about incorrect usage of __slots__ [on] .TP \fB\-3\fR, \fB\-\-properties\fR using properties with classic classes [on] .TP \fB\-\-emptyslots\fR check if __slots__ is empty [on] .TP \fB\-D\fR, \fB\-\-intdivide\fR check if using integer division [on] .TP \fB\-w\fR, \fB\-\-shadow\fR check if local variable shadows a global [on] .HP \fB\-s\fR, \fB\-\-shadowbuiltin\fR check if a variable shadows a builtin [on] .SS "Security:" .TP \fB\-\-input\fR check if input() is used [on] .TP \fB\-6\fR, \fB\-\-exec\fR check if the exec statement is used [off] .SS "Suppressions:" .TP \fB\-q\fR, \fB\-\-stdlib\fR ignore warnings from files under standard library [off] .TP \fB\-b\fR, \fB\-\-blacklist\fR ignore warnings from the list of modules [['Tkinter', 'wxPython', 'gtk', 'GTK', 'GDK']] .TP \fB\-Z\fR, \fB\-\-varlist\fR ignore global variables not used if name is one of these values [['__version__', '__warningregistry__', '__all__', '__credits__', '__test__', '__author__', '__email__', '__revision__', '__id__', '__copyright__', '__license__', '__date__']] .TP \fB\-E\fR, \fB\-\-unusednames\fR ignore unused locals/arguments if name is one of these values [['_', 'empty', 'unused', 'dummy']] .TP \fB\-\-deprecated\fR ignore use of deprecated modules/functions [on] .SS "Complexity:" .TP \fB\-L\fR, \fB\-\-maxlines\fR maximum lines in a function [200] .TP \fB\-B\fR, \fB\-\-maxbranches\fR maximum branches in a function [50] .TP \fB\-R\fR, \fB\-\-maxreturns\fR maximum returns in a function [10] .TP \fB\-J\fR, \fB\-\-maxargs\fR maximum # of arguments to a function [10] .TP \fB\-K\fR, \fB\-\-maxlocals\fR maximum # of locals in a function [40] .TP \fB\-5\fR, \fB\-\-maxrefs\fR maximum # of identifier references (Law of Demeter) [5] .TP \fB\-m\fR, \fB\-\-moduledoc\fR no module doc strings [off] .TP \fB\-c\fR, \fB\-\-classdoc\fR no class doc strings [off] .TP \fB\-f\fR, \fB\-\-funcdoc\fR no function/method doc strings [off] .SS "Debug:" .TP \fB\-\-rcfile\fR print a .pycheckrc file generated from command line args .TP \fB\-P\fR, \fB\-\-printparse\fR print internal checker parse structures [off] .TP \fB\-d\fR, \fB\-\-debug\fR turn on debugging for checker [off] .TP \fB\-Q\fR, \fB\-\-quiet\fR turn off all output except warnings [off] .TP \fB\-V\fR, \fB\-\-version\fR print the version of PyChecker and exit .SH AUTHOR Pychecker was written by Neal Norwitz and Eric C. Newton. Other contributors are listed in .B /usr/share/doc/pychecker/MAINTAINERS This manual page was written by Fredrik Steen for the Debian GNU/Linux system (but may be used by others). It has been subsequently modified by Kenneth J. Pronovici . .SH "SEE ALSO" \fBpython\fP(1) Running .B pychecker \-\-help may provide more complete documentation of program options. The pychecker web page at .B contains some guidance on using the program. debian/source/0002775000000000000000000000000012143266243010475 5ustar debian/source/format0000664000000000000000000000001412143254543011701 0ustar 3.0 (quilt) debian/README.Debian0000664000000000000000000000234412143254543011237 0ustar The pychecker Python package is installed as a public package by the dh_python2 infrastructure. This means that you can import pychecker modules directly from any "current" version of Python. (The "current" version of Python is defined by the Debian Python policy and the dh_python2 infrastructure. As of this writing, Python 2.6 and 2.7 are current.) This package does still support use of $PYTHONVER on the command-line. You can use this functionality to specify which version of Python the pychecker code should be executed with. For instance, you can use something like this: PYTHONVER=2.6 pychecker file.py Unfortunately, now that the new Python infrastructure is in place, this functionality is less helpful than it used to be. A user can no longer invoke any arbitrary python interpreter installed in /usr/bin. Only one of the "current" Python interpreters will work. The pychecker2 code is also included in the Debian package. Pychecker itself (the utility) does not use this code. However, the Debian package for SPE uses it. Upstream is OK with me including this code in the Debian package, as long as everyone is aware that pychecker2 is not under active development. Kenneth J. Pronovici 24 Apr 2013 debian/copyright0000664000000000000000000000413512143254543011131 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: pychecker Upstream-Contact: Thomas Vander Stichele Source: http://pychecker.sourceforge.net/ Files: * Copyright: 2000-2004 MetaSlash Inc. 2005 Google, Inc. License: BSD-3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. . - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . - Neither name of MetaSlash Inc. nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Files: debian/* Copyright: 2001-2003 Arto Jantunen 2003-2013 Kenneth J. Pronovici 2011-2013 Sandro Tosi License: Copying and distribution of these files, with or without modification, is permitted in any medium without royalty provided the copyright notice and this notice are preserved. debian/docs0000664000000000000000000000004312143254543010043 0ustar README TODO KNOWN_BUGS MAINTAINERS debian/control0000664000000000000000000000172712143266210010577 0ustar Source: pychecker Section: devel Priority: optional Maintainer: Python Applications Packaging Team Uploaders: Kenneth J. Pronovici , Sandro Tosi Homepage: http://pychecker.sourceforge.net/ Vcs-Svn: svn://anonscm.debian.org/python-apps/packages/pychecker/trunk/ Vcs-Browser: http://anonscm.debian.org/viewvc/python-apps/packages/pychecker/trunk/ Build-Depends: debhelper (>= 9), python-all (>= 2.6.6-3~) Standards-Version: 3.9.4.0 X-Python-Version: >= 2.1 Package: pychecker Architecture: all Depends: ${python:Depends}, ${misc:Depends} Description: tool to find common bugs in Python source code PyChecker is a tool for finding common bugs in Python source code. It finds problems that are typically caught by a compiler for less dynamic languages, like C and C++. Because of the dynamic nature of Python, some warnings may be incorrect; however, spurious warnings should be fairly infrequent. debian/patches/0002775000000000000000000000000012143266243010624 5ustar debian/patches/remove-bashisms.patch0000664000000000000000000000115412143254543014750 0ustar # Description: Remove bashisms from shell scripts. # For squeeze, Debian has changed /bin/sh so it is really /bin/dash rather # than /bin/bash. Some scripts that I need to run include bashisms and are # not compatible with /bin/dash. This patch fixes those scripts. # Author: Kenneth J. Pronovici --- a/test_check.sh +++ b/test_check.sh @@ -20,7 +20,7 @@ TMP=`mktemp -t -d tmp.pychecker.test_check.XXXXXXXXXX` -function get_expected () +get_expected () # Find a versioned expected output file # Use the expected one with the highest version equal to or lower than # our python version debian/patches/spe-improvements.patch0000664000000000000000000000502112143254543015156 0ustar # Description: Apply SPE improvements to main.py. # The SPE (Stani's Python Editor) folks have made some minor improvements to # pychecker2/main.py, to make it handle errors better and make it more # flexible. The changes are straightforward and look safe to me. Since SPE is # already using them this implies that they work properly. # Bug-Debian: http://bugs.debian.org/453092 # Forwarded: http://sourceforge.net/tracker/?func=detail&aid=1845213&group_id=24686&atid=382219 # Author: SPE (Stani's Python Editor), http://pythonide.stani.be # Reviewed-By: Kenneth J. Pronovici --- a/pychecker2/main.py +++ b/pychecker2/main.py @@ -1,5 +1,28 @@ import sys from os.path import dirname, realpath +import os + +def userPath(dirname=''): + """'safer' function to find user path.""" + # 'safer' function to find user path: look for one of these directories + try: + path = os.path.expanduser("~") + if os.path.isdir(path): + return os.path.join(path, dirname) + except: + pass + for evar in ('HOME', 'USERPROFILE', 'TMP'): + try: + path = os.environ[evar] + if os.path.isdir(path): + return os.path.join(path, dirname) + except: + pass + #if no match found, use module directory + return os.path.join(os.path.dirname(os.path.abspath(__file__)), dirname) + +CACHE_FILE = userPath(".pychecker_cache") + sys.path.append(dirname(dirname(realpath(sys.argv[0])))) from pychecker2.Check import CheckList @@ -16,8 +39,6 @@ from pychecker2 import ConditionalChecks from pychecker2 import FormatStringChecks -CACHE_FILE = '/tmp/t' - def print_warnings(f, out): if not f.warnings: return 0 @@ -69,7 +90,7 @@ options = Options.Options() try: checker = cPickle.load(open(CACHE_FILE, 'rb')) - except (EOFError, IOError): + except (EOFError, IOError, ImportError): checker = create_checklist(options) try: @@ -79,10 +100,17 @@ options.usage(sys.argv[0], sys.stderr) return 1 + # Properly load local modules relative to the file which is being checked + sys_path = sys.path[:] for f in files: + f_dir = dirname(f.name) + sys.path= sys_path[:] + if f_dir not in sys.path: + sys.path.insert(0,f_dir) checker.check_file(f) if options.incremental and not options.profile: print_warnings(f, sys.stdout) + sys.path = sys_path result = 0 if not options.incremental and not options.profile: debian/patches/fix-version.patch0000664000000000000000000000104412143254543014113 0ustar # Description: Fix the reported upstream version. # Upstream does not report the proper version, so I am fixing it here. # Author: Kenneth J. Pronovici --- a/pychecker/Config.py +++ b/pychecker/Config.py @@ -33,7 +33,7 @@ _RC_FILE = ".pycheckrc" CHECKER_VAR = '__pychecker__' -_VERSION = '0.8.18' +_VERSION = '0.8.19' _DEFAULT_BLACK_LIST = [ "Tkinter", "wxPython", "gtk", "GTK", "GDK", ] _DEFAULT_VARIABLE_IGNORE_LIST = [ '__version__', '__warningregistry__', --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.18 +0.8.19 debian/patches/remove-shebang.patch0000664000000000000000000000042112143254543014542 0ustar # Description: Remove shebang (#!) from .py files to comply with policy. # Author: Kenneth J. Pronovici --- a/pychecker/checker.py +++ b/pychecker/checker.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- Mode: Python -*- # vi:si:et:sw=4:sts=4:ts=4 debian/patches/tweak-setup-py.patch0000664000000000000000000000207612143254543014547 0ustar # Description: Customize the upstream setup.py. # For Debian, we distribute pychecker2 even through upstream doesn't. # We also distribute a different customized pychecker script. # Author: Kenneth J. Pronovici --- a/setup.py +++ b/setup.py @@ -258,9 +258,9 @@ kw = { 'name' : "PyChecker" 'author' : "Neal Norwitz", 'author_email' : "nnorwitz@gmail.com", 'url' : "http://pychecker.sourceforge.net/", - 'packages' : [ 'pychecker', ], - 'scripts' : [ "pychecker" ], # note: will be replaced by customized action - 'data_files' : [ ( "pychecker", DATA_FILES, ) ], + 'packages' : [ 'pychecker', 'pychecker2', ], # Debian includes pychecker2, which upstream does not + #'scripts' : [ "pychecker" ], # note: will be replaced by customized action + #'data_files' : [ ( "pychecker", DATA_FILES, ) ], 'long_description' : LONG_DESCRIPTION, 'cmdclass' : CUSTOMIZED_ACTIONS, } debian/patches/dist-packages.patch0000664000000000000000000000146612143254543014371 0ustar # Description: Support Debian-specific standard library location. # Debian has chosen to put Python standard libraries in dist-packages rather # than site-packages. However, this is somewhat non-standard, and confuses # pychecker. This patch adds support for dist-packages in addition to # site-packages. # Bug-Debian: http://bugs.debian.org/648426 # Author: Nigel Evans # Reviewed-By: Kenneth J. Pronovici --- a/pychecker/warn.py +++ b/pychecker/warn.py @@ -451,7 +451,7 @@ ret = [] for std_lib in std_libs: path = os.path.split(std_lib) - if path[1] == 'site-packages' : + if path[1] in ('dist-packages', 'site-packages') : ret.append(path[0]) return ret except ImportError : debian/patches/put-back-missing-files-from-cvs.patch0000664000000000000000000113705112143254543017662 0ustar # Description: Add back missing files. # This patch adds back a *huge* number of files that were mistakenly # not included in the official upstream 0.8.19 tarball. These files # will be included in the 0.8.20 release, using a new MANIFEST.in # which I provided. However, for the time being upstream has asked # me to deal with this problem by patching the Debian package. All # of the extra files included in this patch were pulled directly from # upstream CVS using 'cvs co -r v0_8_19'. # Author: Kenneth J. Pronovici --- /dev/null +++ pychecker-0.8.19/test_check.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +TESTS="test_input/test[1-9]*.py" +# comment out to use python from path +#PYTHON="python2" +#PYTHON="$HOME/build/python/2_3/python" +#PYTHON="$PYTHON -tt coverage.py -x" +#PYTHON="/usr/bin/python2.3" + +if [ "$PYTHON" = "" ]; then + PYTHON=python +fi + +if [ $# -gt 0 ]; then + TESTS="" + for arg in $* ; do + TESTS="$TESTS test_input/test${arg}.py" + done +fi + +TMP=`mktemp -t -d tmp.pychecker.test_check.XXXXXXXXXX` + +function get_expected () +# Find a versioned expected output file +# Use the expected one with the highest version equal to or lower than +# our python version +# Fall back to the unversioned one +# arg1: test name +# sets EXPECTED +{ + local NAME=$1 + + local VERSION=`$PYTHON -c "import sys ; print '%d.%d' % sys.version_info[0:2]"` + + # start with the unversioned one + EXPECTED=test_expected/$NAME + + # FIXME: using \< and \> is not elegant, but python's versioning is + # well-behaved + ALL=`ls test_expected/$NAME-* 2> /dev/null` + if test -z "$ALL" + then + return + fi + + for CANDIDATE in $ALL + do + WANTED=test_expected/$NAME-$VERSION + # echo candidate $CANDIDATE, with our version $WANTED + if test ! $CANDIDATE \> $WANTED + then + # echo $CANDIDATE sorts before $WANTED + if test $CANDIDATE \> $EXPECTED + then + # echo $CANDIDATE sorts after $EXPECTED, so new EXPECTED is $CANDIDATE + EXPECTED=$CANDIDATE + fi + # else + # echo $CANDIDATE sorts equal or after $WANTED + fi + done + # echo EXPECTED: $EXPECTED +} + + +error=0 + +VERSION=`$PYTHON -c "import sys ; print '%d.%d' % sys.version_info[0:2]"` +FAILED="" +NO_EXPECTED_RESULTS="" +for test_file in $TESTS ; do + echo "Testing $test_file ..." + test_name=`basename $test_file .py` + get_expected $test_name + + # make sure to use the -F option for this special test + extra_args="" + if [ "$test_file" = "test_input/test39.py" ]; then + extra_args="-F test_input/pycheckrc" + fi + + test_path=$TMP/$test_name + $PYTHON -tt ./pychecker/checker.py --limit 0 --moduledoc --classdoc --no-argsused $extra_args $test_file 2>&1 | egrep -v '\[[0-9]+ refs\]$' > $test_path + # mangle any system path-like paths that warning lines start with; + # this allows us to compare to fixed expected output irrespective + # of where python is installed, making it reproducable + # FIXME: someone translate this to an equivalent line of python or sed + perl -i -p -e 's@.*/lib(.*)/python\d.\d/@[system path]/@g' $test_path + diff -u $EXPECTED $test_path + if [ $? -ne 0 ]; then + error=`expr $error + 1` + echo " $test_name FAILED; output different from expected in $EXPECTED" + FAILED="$FAILED $test_name" + fi + rm -f $test_path +done + +if [ $error -ne 0 ]; then + echo "" + echo "$error TESTS FAILED: $FAILED" +else + echo "ALL TESTS PASSED" +fi + +if [ "$NO_EXPECTED_RESULTS" != "" ]; then + echo " WARNING no expected results for: $NO_EXPECTED_RESULTS" +fi + +rm -rf $TMP + +exit $error --- /dev/null +++ pychecker-0.8.19/HACKING @@ -0,0 +1,62 @@ +TESTSUITE +--------- + +The old testsuite is in the root directory, and runs through shell code. + - test_input contains all of the python code files to be checked. + - test_expected contains the expected output + - test_check.sh runs the testsuite + +The new testsuite is in the test/ directory and uses the unittest module. + - test/test_input contains all of the python code files to be checked. + - test/test_expected contains the expected output + - test/ contains the unittest modules + - test/common.py contains common classes used in the unittest modules + - test/main.py is the main test loader + - run the testsuite either with: + PYTHONPATH=`pwd`:$PYTHONPATH python test/main.py + or + trial test + +Adding a test: + - add a TestCase in test/test_(type).py + - add an input file in test/test_input/test_(name).py + - run the test to generate an expected output for this test + - adapt it, since it might not be what you want, if for example it generates + a warning that it shouldn't + +UPDATE TO NEW PYTHON VERSION +---------------------------- + - test/test_pychecker_CodeChecks has a test that fails on missing + opcode handlers for new opcodes + - add version codes to pychecker/utils.py (PYTHON_X_Y) + - compare pychecker/OP.py with opcodes: + - check/update the arrays for + cmp_op, hascompare, hasconst, hasfree, hasjabs, hasjrel, haslocal, hasname + - update some of the OP.py specific things: + - IS_CONDITIONAL_JUMP + - op checkers at the top + - add dispatchers for new opcodes in pychecker/CodeChecks.py + - see http://docs.python.org/library/dis.html + - figure out when they were added; in python source code: + svn blame Lib/opcode.py + svn diff -c [changeset that added/changed your opcode] + - add future keywords in pychecker/python.py + +HISTORY +------- + - Python 2.7: + - changes: + LIST_APPEND moved from 18 to 94 + BUILD_MAP to IMPORT_FROM bumped from 104-108 to 105-109 + EXTENDED_ARG bumped from 143 to 145 + - added: + BUILD_SET + JUMP_IF_FALSE/TRUE_OR_POP + POP_JUMP_IF_FALSE/TRUE + SET_ADD/MAP_ADD + - removed: + JUMP_IF_FALSE/JUMP_IF_TRUE + +BUILDBOT +-------- +A buildbot is set up at http://build.fluendo.com:8200/ --- /dev/null +++ pychecker-0.8.19/test_input/test66.py @@ -0,0 +1,7 @@ +'d' + +from time import time, sleep + +def x(): + print time, sleep + --- /dev/null +++ pychecker-0.8.19/test_input/import73.py @@ -0,0 +1,9 @@ +class AbstractLib: + "" + def __init__(self): + pass + + def abstract(self): + "This is doc" + "this is an expression, sneaky" + raise NotImplementedError("This method must be overridden") --- /dev/null +++ pychecker-0.8.19/test_input/test51.py @@ -0,0 +1,19 @@ +'d' + +def x(): + n = [] + d = {} + print n[5] + print n[5,-3] + print n[1,3] + print n[1:3] + print n[1:-3] + + print d[5] + print d[5,-3] + print d[1,3] + print d[1:3] + print d[1:-3] + + print [1, 2][1] + --- /dev/null +++ pychecker-0.8.19/test_input/test73.py @@ -0,0 +1,37 @@ +'test abstract classes' + +__pychecker__ = 'no-classdoc' + +class Abstract: + def f(self): raise NotImplementedError, "override in subclass" + def g(self): raise NotImplementedError +class ConcreteBad(Abstract): + def g(self): pass +class ConcreteGood(ConcreteBad): + def f(self): pass +a = Abstract() # error +cb = ConcreteBad() # error +cg = ConcreteGood() # ok, f defined + +class ConcreteInst: + def f(self): raise SystemError("not yet ready for prime time") +ch = ConcreteInst() # ok, raises SystemError + +class AbstractInst: + def f(self): raise NotImplementedError("not yet ready for prime time") +ch = AbstractInst() + +cb.g() +def f(): + class MoreBad(Abstract): + def g(): pass + _ = MoreBad() # FIXME, error not caught + +import import73 +class ImplAbstract(import73.AbstractLib): + def __init__(self): + import73.AbstractLib.__init__(self) + +def lib_example(): + _ = import73.AbstractLib() # error + unused = ImplAbstract() # error --- /dev/null +++ pychecker-0.8.19/test_input/test93.py @@ -0,0 +1,15 @@ +'docstring' + +def x(a, b): + c = getattr(a, b) + c = getattr(a, b, None) + c = getattr(a, 'c') + c = getattr(a, 'c', None) + print c + + setattr(a, b, None) + setattr(a, 'b', None) + +def y(a): + """Using a keyword to getattr, should not generate a warning.""" + return getattr(a, "print") --- /dev/null +++ pychecker-0.8.19/test_input/test10.py @@ -0,0 +1,8 @@ +"doc" + +from xml.sax import saxutils + +def afunc(): + stuff = saxutils.escape.make_parser('junk') + return stuff + --- /dev/null +++ pychecker-0.8.19/test_input/test59.py @@ -0,0 +1,31 @@ +'d' + +def x1(a, b, c = [], d = {}): + c.reverse() + d.update({ a: b}) + +def x2(a, b, c, d): + c.reverse() + d.update({ a: b}) + +def y(a, b, c = [], d = {}): + print a, b, c, d + +class X: + 'd' + def x(self) : pass + +def zz(x = X()): + print x.x() + +def zz2(a = [], b = {}): + a[0] = b + b[0] = a + +def aaa1(a, b, c = [], d = {}): + print c.index(a) + print c.count(a) + print d.get(b) + print d.has_key(b) + print d.keys() + print d[b] --- /dev/null +++ pychecker-0.8.19/test_input/import56b.py @@ -0,0 +1,6 @@ +'doc' + +class Bar: + 'doc' + def __init__(self): pass + --- /dev/null +++ pychecker-0.8.19/test_input/test85.py @@ -0,0 +1,22 @@ +'''test return (x and 'true' or 'false') idiom''' + +def f1(test): + 'should not warn' + return test and 'true' or 'false' + +def f2(test): + 'should not warn about None' + return test and 'true' or None + +def f3(test): + 'should warn about None' + return test and None or 'false' + +def f4(test): + 'should warn' + return test and [] or 0 + +def f5(test): + 'should not warn' + return test and 'true' or 0 + --- /dev/null +++ pychecker-0.8.19/test_input/test103.py @@ -0,0 +1,5 @@ +"""Multiple generator expresstions should not cause a redefinition warning.""" + +def foo(): + print ' '.join(str(x) for x in range(10)) + print ' '.join(str(x) for x in range(10)) --- /dev/null +++ pychecker-0.8.19/test_input/test6.py @@ -0,0 +1,31 @@ + +"doc" + +from xml.dom import pulldom + +class X(pulldom.PullDOM) : + "doc" + def __init__(self): + "shouldn't be a warning" + pulldom.PullDOM.__init__(self) + +class Y(Exception): + "doc" + def __init__(self, err): + "this shouldn't produce a warning" + Exception.__init__(self, err) + +class Z(Y): + "doc" + def __init__(self, err): + "this shouldn't produce a warning" + apply(Y.__init__, (self, err)) + +def uuu(func): + "shouldn't crash" + return tuple([i for i in func() if func(globals()[i])]) + +def yyy(): + "shouldn't crash" + map(apply, globals().keys(), ((),) * len(globals()), globals().values()) + --- /dev/null +++ pychecker-0.8.19/test_input/test22.py @@ -0,0 +1,86 @@ +'d' + +def y(): + print '%d %f %s' % (1, 2.2, 'sdf') + + print '%d %f %s %d' % (1, 2.2, 'sdf') + + aaa = bbb = 1 + eee = 0 + print '%(aaa)d %(bbb)f %(ccc)s %(ddd)s' % locals() + + b = 0 + print '%()s %(b)d' % locals() + + print '%(b) %(aaa)d' % locals() + print '%(aaa)d %(b)' % locals() + + print '%*d' % (2, 2) + print '%*d' % (2, 2, 3) + + print '%*.*f' % (5, 2, 2.0) + print '%*.*f' % (5, 2, 2.0, 3) + + print '%z %f %s' % (1, 2.2, 'sdf') + print '%d %J %s' % (1, 2.2, 'sdf') + print '%***f' % (5, 2, 2.0, 3) + + print '%(aaa)d %d' % locals() + print '%(aaa)*d' % locals() + jjj = 1.0 + print '%(jjj)*.*f' % locals() + + fmt = '%d %s %d' + print fmt % (aaa, bbb) + + +_F = '%d %d' + +def ZZ(): + print _F % 5 + print _F % (5, 5) + print _F % (5, 5, 5) + + F = '%d' + print F % 5 + print F % (5, 5, 5) + + t1 = (1,) + t2 = (1,2) + print F % t1 + print F % t2 + +def YY(item): + print '%(a)s %(b)s' % { 'a': '5', 'b': '7' } + print '%(a)s %(b)s' % item + d = { 'a': '5', 'b': '7' } + print '%(a)s %(b)s' % d + +def string_multiply(): + # these are right + print '%d ' * 3 % (1, 2, 3) + print ('%d ' * 3) % (1, 2, 3) + + # these are wrong + print '%d ' * 2 % (1, 2, 3) + print '%d ' * 3 % (1, 2, 3, 4) + print ('%d ' * 4) % (1, 2) + +def check_vars1(): + a = b = c = 5 + print '%(a)d %(b)d' % vars() + +def check_vars2(): + a = b = c = 5 + print '%(a)d %(b)d' % vars(c) + +def check_modulo_1(): + print '%s' % '1' + print '%s' % 1 + print .55555 % 1 + print 55555 % 1 + f = 55555.55 + print f % 1 + +def check_bad_format_end_percent(arg): + print 'ha, better not crash %' % arg --- /dev/null +++ pychecker-0.8.19/test_input/test54.py @@ -0,0 +1,20 @@ +'d' + +real_global = 0 + +def f(a, b, c): + del a + del z + z = 0 + del a + del z + + print a, b, c + + global no_global + del no_global + +if __name__ == '__main__': + del another_non_existant_global + del real_global + --- /dev/null +++ pychecker-0.8.19/test_input/test35.py @@ -0,0 +1,13 @@ + +__pychecker__ = '--no-namedargs --no-import --no-var --no-privatevar --no-moduledoc --funcdoc' + +import re + +_NOT_USED1 = None +NOT_USED2 = None + +def x(a, b) : pass + +def y(): + x(b=1, a=2) + --- /dev/null +++ pychecker-0.8.19/test_input/import24.py @@ -0,0 +1,14 @@ +'doc' + +class Aaa: + def __init__(self): + self.a = 1 + +class Bbb(Aaa): + def __init__(self): + self.b = 1 + +def func24(): + return 53 + +shadow = 5 --- /dev/null +++ pychecker-0.8.19/test_input/test100.py @@ -0,0 +1,15 @@ +# https://sourceforge.net/tracker/index.php?func=detail&aid=1563494&group_id=24686&atid=382217 +# see zope.interface.declarations.Declaration +# for a real-world one line test, pycheck "import zope.interface.declarations" + +'d' +class D: + 'd' + __bases__ = () + + # this repr avoids getting the default repr, which shows an id + # which changes between test runs + __repr__ = classmethod(lambda cls: 'D') + +# instantiating triggers the bug +d = D() --- /dev/null +++ pychecker-0.8.19/test_input/test18.py @@ -0,0 +1,44 @@ +'d' + +class A: + "d" + def __init__(self): pass + +class X: + "d" + def __init__(self, x): pass + +class Y: + "d" + def __init__(self, x, y, z): pass + +class Z: + "d" + def __init__(self, x, y, z, *args, **kw): pass + +def j(): + A() + A(1) + + X() + X(1) + X(1, 2) + X(1, 2, 3) + X(1, 2, 3, 4) + + Y() + Y(1) + Y(1, 2) + Y(1, 2, 3) + Y(1, 2, 3, 4) + + Z() + Z(1) + Z(1, 2) + Z(1, 2, 3) + Z(1, 2, 3, 4) + Z(1, 2, 3, 4, 5) + Z(1, 2, 3, 4, 5, 6) + Z(1, 2, 3, 4, k=1, j=2, m=3, f=5) + + --- /dev/null +++ pychecker-0.8.19/test_input/test47.py @@ -0,0 +1,7 @@ +'there was a spurious warning when the module and class name were the same' + +import import47 + +class jj(import47.import47): + 'doc' + --- /dev/null +++ pychecker-0.8.19/test_input/test12.py @@ -0,0 +1,8 @@ +"shouldn't produce any warnings" + +from xml.sax import handler + +class GetGUI(handler.DTDHandler): + "shouldn't produce any warnings" + pass + --- /dev/null +++ pychecker-0.8.19/test_input/test60.py @@ -0,0 +1,22 @@ +'d' + +def __repr__(self): + print `self` + +class X: + 'd' + def __repr__(self): + print `self` + +class Y: + 'd' + def __init__(self): + self.x = 0 + def __repr__(self): + print `self.x` + +class Z: + 'd' + def other_method(self): + print `self` + --- /dev/null +++ pychecker-0.8.19/test_input/test96.py @@ -0,0 +1,15 @@ +'''test using string.find() in if statement as a boolean. it returns an int''' + +class X: + '''check string.find() usage''' + def foo(self): + s = 'abc' + if s.find('ab'): + print 'this is a bug' + if not s.find('ab'): + print 'this is also a bug' + if s.find('ab') >= 0: + print 'this is not a bug' + if s.find('ab') < 0: + print 'this also is not a bug' + --- /dev/null +++ pychecker-0.8.19/test_input/test46.py @@ -0,0 +1,7 @@ +'d' + +def x(): pass + +import test46 +from test46 import x +from test46 import * --- /dev/null +++ pychecker-0.8.19/test_input/test65.py @@ -0,0 +1,21 @@ +'test nested scopes' + +from __future__ import nested_scopes + +def x(p): + def y(): + print p + + y() + print p + +def a(p): + def y(): + print p + + y() + +def chop(seq,size): + chunk = lambda i: seq[i:i+size] + return map(chunk,range(len(seq))) + --- /dev/null +++ pychecker-0.8.19/test_input/test24.py @@ -0,0 +1,12 @@ +'doc' + +from import24 import * + +b = Bbb() + +def xxx(): + print func24(1) + +def func(shadow): + print shadow + --- /dev/null +++ pychecker-0.8.19/test_input/test68.py @@ -0,0 +1,170 @@ +'test implicit returns' + +__pychecker__ = 'implicitreturns' + +def func1(x): + 'should not produce a warning' + if x == 1: + return 1 + return 0 + +def func2(x): + 'should produce a warning' + if x == 1: + return 1 + +def func3(x): + 'should not produce a warning' + while 1: + if x == 1: + return 1 + x = x / 2 + return 0 + +def func4(x): + 'should not produce a warning' + while 1: + if x == 1: + return 1 + x = x / 2 + +def func5(x): + 'should not produce a warning' + while 1: + if x == 1: + return 1 + return 0 + +def func6(x): + 'should produce a warning' + while 1: + if x == 1: + return 1 + break + +def func7(x): + 'should not produce a warning' + try: + print x + return 2 + except: + pass + return 0 + +def func8(x): + 'should produce a warning' + try: + if x == 1: + return 3 + if x == 2: + return 6 + except: + pass + +def func9(x): + 'should not produce a warning' + try: + return x + except: + return 0 + +def func10(x): + 'should not produce a warning' + if x: + raise ValueError + +def func11(x): + 'should not produce a warning' + if x: + raise ValueError + return 5 + +def func12(x): + 'should not produce a warning' + raise ValueError, 'test' + +def func13(x): + 'should not produce a warning' + if x == 1: + return 1 + else: + return 0 + +def func14(x): + 'should not produce a warning' + try: + if x == 1: + return 3 + return 6 + except: + raise + +def func15(x): + 'should not produce a warning' + try: + return x.j + except AttributeError: + return 0 + +def func16(x): + 'should not produce a warning' + try: + return x.j + except AttributeError: + raise + +def func17(x): + 'should not produce a warning' + try: + return x.j + except (AttributeError, KeyError, IndexError): + return 0 + +def func18(x): + if x == 'n': + return x + if x != 'j': + raise AttributeError + +def func19(x): + 'should not produce a warning' + while 1: + if x: + x = x + 1 + return 1 + +def func20(x): + 'should produce a warning' + while 1: + if x: + break + return 1 + +def func21(x): + 'should not produce a warning' + try: + if x == 1: + return 3 + return 6 + finally: + print 'do nothing' + +def func22(x): + 'should not produce a warning' + while 1: + for _ in range(10) : + x = x / 2 + break + return 1 + +def catchup(slave, image, inProgress): + d = func1.bogus() + def next_func(): + defer = slave.call('', image.next()) + try: + defer.add(d.errback) + except: + slave.call(inProgress) + next_func() + return d + --- /dev/null +++ pychecker-0.8.19/test_input/test75.py @@ -0,0 +1,87 @@ +'test slots & property, this will only work in Python 2.2' + +class A: + 'warn about using slots in classic classes' + __slots__ = ('a',) + +try: + class B(object): + 'no warning' + __slots__ = ('a',) + + class C(object): + 'warn about using empty slots' + __slots__ = () + + class D(object): + "don't warn about using empty slots" + __pychecker__ = '--no-emptyslots' + __slots__ = () + + class E: + 'this should generate a warning for using properties w/classic classes' + def getx(self): + print 'get x' + return 5 + x = property(getx) + + class F(object): + 'this should not generate a warning for using properties' + def getx(self): + print 'get x' + return 5 + x = property(getx) + + class Solution(list): + 'this should not generate a warning or crash' + def __init__(self): + pass + + class MethodArgNames: + 'check warnings for static/class methods for first arg name' + def __init__(self, *args): pass + + # should warn + def nn(self, *args): pass + nn = classmethod(nn) + + # should warn + def mm(self, *args): pass + mm = staticmethod(mm) + + # should not warn + def oo(cls, *args): pass + oo = classmethod(oo) + + # should not warn + def pp(*args): pass + pp = staticmethod(pp) + + # should not warn + def qq(): pass + qq = staticmethod(qq) + + # should not warn + def rr(klass, *args): pass + rr = classmethod(rr) + + class Bug4(object): + '''doc''' + def static(arg1, arg2): + return arg1+arg2 + static = staticmethod(static) + + def buggy(self): + return self.static(1,2) + + class Slots(dict): + 'doc' + pass + + class Foo(object): + 'doc' + __slots__ = Slots() + +except NameError: + pass + --- /dev/null +++ pychecker-0.8.19/test_input/test21.py @@ -0,0 +1,57 @@ +'test inconsistent return types' + +a, b = 0, 0 + +def f(z): + 'should be a warning' + if z: + return 1 + return [] + +def g(z): + 'should be a warning' + if z: + return (1, 2) + return [] + +def h(z): + 'should be a warning' + if z: + return {} + return [] + +def y(): + 'should not be a warning' + if a: return 1 + elif b: return 0 + else : return cmp(a, b) + +def z(): + 'should not be a warning' + if b: return b, a, globals() + return 1, 2, 3 + +class A: + 'test returning base class' + +class B(A): + 'test returning derived class' + +def x(num): + if num == 1: + return A() + if num == 2: + return B() + return None + +class C: + 'test returning "inconsistent" types from __getattr__ which is allowed' + def __getattr__(self, attr): + if attr == 'a': + return 1 + if attr == 'b': + return 3.1415926 + if attr == 'b': + return 'string' + raise AttributeError, 'no attr ' + attr + ' is a bad attr' + --- /dev/null +++ pychecker-0.8.19/test_input/test19.py @@ -0,0 +1,10 @@ +'d' + +import UserDict + +def y(): + UserDict.UserDict() + UserDict.UserDict({}) + UserDict.UserDict({}, 0) + UserDict.UserDict({}, 0, 1) + --- /dev/null +++ pychecker-0.8.19/test_input/test90.py @@ -0,0 +1,22 @@ +'test using is/is not on literals' + +def x(a, b, c): + print a is 1 + print a is 's' + print a is 1.32 + print a is () + print a is [] + print a is {} + print a is b + print b is c + print b is None + + print a is not 1 + print a is not 's' + print a is not 1.32 + print a is not () + print a is not [] + print a is not {} + print a is not b + print b is not c + print b is not None --- /dev/null +++ pychecker-0.8.19/test_input/test15.py @@ -0,0 +1,39 @@ +"doc" + +def xx(**kw): + return None + +def yy(): + c = yy + g, h = 1, 2 + xx(a='', b=c.a.d.f, e=5, jj=xx(j=5), f=(g+h), k=("%s" % "df")) + +def zz(): + b = zz + xx(b=(1, 2, 3), c={ 'a': b}, d=[1, 2, 3], k=(1 < 2)) + +def aa(obj): + print obj.x.y + print obj.x.y.z + print obj.x.y.z.a + print obj.x.y.z.a.b + print obj.x.y.z.a.b.c + +class Obj: + 'd' + def __init__(self, xx): + self.xx = xx + self.xx.y = 0 + self.xx.y.z = 0 + self.xx.y.z.a = 0 + self.xx.y.z.a.b = 0 + self.xx.y.z.a.b.c = 0 + + def prn(self): + print self.xx + print self.xx.y + print self.xx.y.z + print self.xx.y.z.a + print self.xx.y.z.a.b + print self.xx.y.z.a.b.c + --- /dev/null +++ pychecker-0.8.19/test_input/test37.py @@ -0,0 +1,7 @@ +'d' + +import struct +from import37 import Test + +def x(): + print struct --- /dev/null +++ pychecker-0.8.19/test_input/test67.py @@ -0,0 +1,16 @@ +'d' + +__pychecker__ = 'members' + +class X: + 'd' + j = 0 + def __init__(self): + self.a = 0 + self.b = 0 + self.c = 0 + self.d = 0 + + def p(self): + print self.b, self.c, self.j + --- /dev/null +++ pychecker-0.8.19/test_input/test48.py @@ -0,0 +1,84 @@ +'d' + +class X: + 'd' + def x(self): pass + def y(self): pass + +def x(): + i, l, d, s, n, e = 0, [], {}, '', None, Ellipsis + i.has_no_method() + l.has_no_method() + d.has_no_method() + s.has_no_method() + n.has_no_method() + e.has_no_method() + + print i.has_no_attr + print l.has_no_attr + print d.has_no_attr + print s.has_no_attr + print n.has_no_attr + print e.has_no_attr + + l.sort() + d.clear() + + d[i] = jj = X() + jj.a() + jj.b() + jj.x() + jj.y() + +def y(): + for j in []: + print j.a() + + +class Z: + 'd' + def __init__(self): pass + def x(self): pass + def y(self): pass + +def zz(): + tt = Z() + tt.a() + tt.b() + tt.x() + tt.y() + +def abc(a, b, c): + # these should all generate a warning for doing nothing + a + b + c + abc + 5 + zz.func_doc + str + +def j343(): + d = {} + d['HOME'] + l = [] + l[5] + d, l + +def jklasdflksdjf(): + d = {} + 5 + 3 + 5 - 3 + 5 / 3. + 5 * 3 + 5 ** 3 + d.get + d[1] + d[1:2] + d, d + [d, d] + +def print_item_to(fp, boundary): + # this should not generate a warning, note comma at end + print >> fp, '\n--' + boundary + '--', + --- /dev/null +++ pychecker-0.8.19/test_input/test84.py @@ -0,0 +1,10 @@ +'this crashed pychecker from calendar.py in Python 2.2' + +class X: + 'd' + def test(self, item): + return [e for e in item].__getslice__() + +# this crashed in 2.2, but not 2.3 +def f(a): + a.a = [x for x in range(2) if x > 1] --- /dev/null +++ pychecker-0.8.19/test_input/import37.py @@ -0,0 +1,7 @@ +'d' + +class Test: + 'doc' + def x(self): + import struct + print struct --- /dev/null +++ pychecker-0.8.19/test_input/test69.py @@ -0,0 +1,22 @@ +'d' + +import import69 + +__pychecker__ = 'callattr' +class B: + 'd' + def __init__(self): pass + +class C(B): + 'd' + __super_init = B.__init__ + def __init__(self): + self.__super_init() + +class D(import69.Alias): + 'd' + __super_init = import69.Alias.__init__ + def __init__(self): + self.__super_init() + + --- /dev/null +++ pychecker-0.8.19/test_input/test1.py @@ -0,0 +1,75 @@ + +import imp +import re + +_NOT_USED1 = None +NOT_USED2 = None + +def getModules(n = 0, j = 3) : + "Return list of modules by removing .py from each entry." + for m in unknownList : + pass + +def jjj(self) : + import sys + print sys.argv + +def jjj2(a, b = None, c = None) : + pass + +def ddd(a, *args): + jjj2() + jjj2(1) + jjj2(1, 2) + jjj2(1, 2, 3) + jjj2(1, 2, 3, 4) + +def ppp(): + ddd() + ddd(1) + ddd(1, 2) + ddd(1, 2, 3) + +class X: + def __init__(self) : + print sys.argv + print self.__class__, self.__doc__, self.__dict__, self.__x__, self.x + self.y = 0 + print self.y + def r(sf): + nofunc() + for i in range(0, len(self.a)) : + jjj(1, 2, 3, k=5) + +class Y(X): + def xxx(self, adf) : + asdf = adf + # jjjj doesn't exist + j = jjjj + # z() doesn't exist + self.z() + adf.mmm.kkk() + # j doesn't exist + self.j = 0 + self.xxx(1, 2) + +def uuu(): + a=1+2 + return a[0], [['a', 'b'], [1,2,3,4]] + +def renderElement(a, b=2, c=3, **kw): + contents = kw + print contents + +def renderItem(text): + return renderElement(1, contents=text, z=1, y=2, x=3) + +def test_kw_lambda(a, b, c): + return renderElement(a, ff=lambda value: '=' + renderItem(b)) + +str = '53' +_ = "blah, don't care, shouldn't warn" + +def getOneImageFromPath(k, v): + d = [] + d.append(id=k, original_flag=v) --- /dev/null +++ pychecker-0.8.19/test_input/test36.py @@ -0,0 +1,40 @@ +'d' + +from types import StringType, NoneType +from string import upper + +def foo(): + return map(lambda x: upper(x), 'testing') + +def func(a, b, *args, **kw): + 'verify no warnings for variables (arguments) used before set' + print a, b, args, kw + +class E(Exception): + 'doc' + + +def x(): + 'instantiate a new E with many args, should not be a warning' + print E('test', 'test', 'test', 'test', 'test', 0) + +def y(): + from string import lower + lower = lower('Unknown option') + +def foobar(x): return x + +def nn(): + print map(lambda x, s=foobar: s(x), [1,2]) + +def start() : + int(args=(lambda x=None: x,)) + +def nn2(): + n = [] + n.append(1) + n.append(1, 2) + n.append((1, 2)) + +def run(): + foobar(x={0:5}) --- /dev/null +++ pychecker-0.8.19/test_input/test33.py @@ -0,0 +1,10 @@ +'d' + +def x(): + print j + j = 0 + +def y(): + for x in []: + print x + --- /dev/null +++ pychecker-0.8.19/test_input/test43.py @@ -0,0 +1,11 @@ +'d' + +class GameObject: + 'd' + # def isIntersecting(self, other): pass + pass + +class SoAndSo(GameObject): + 'd' + def isIntersecting(self, other): + return GameObject.isIntersecting(self, other) --- /dev/null +++ pychecker-0.8.19/test_input/test28.py @@ -0,0 +1,8 @@ +'doc' + +import fnmatch + +class X: + 'doc' + x = filter(lambda f, p = '' : fnmatch.fnmatch(f, p), []) + --- /dev/null +++ pychecker-0.8.19/test_input/test20.py @@ -0,0 +1,41 @@ +'this test will fail unless -r/--returnvalues is used' + +def func0(x): + 'should not be a warning' + return 0 + +def func1(x): + 'should be a warning implicit/explicit' + if x == 0 : + return 1 + +def func2(x): + 'should not be a warning' + if x == 0 : + return + +def func3(x): + 'should be a warning' + if x == 0 : + return 1, 2 + return 1 + +def func4(x): + 'should not be a warning, difficult to deal with' + c = (1, 2) + if x == 0 : + return c + return 9, 8 + +def func5(x): + 'should not be a warning' + if x == 0 : + return 1, 2 + return 9, 8 + +def func6(x): + 'should be a warning' + if x == 0 : + return 1, 2 + return 9, 8, 7 + --- /dev/null +++ pychecker-0.8.19/test_input/test4.py @@ -0,0 +1,32 @@ + +import UserDict + +class jj(UserDict.UserDict) : + "jj" + def __init__(self): + UserDict.UserDict.__init__(self, None) + +class jj2(UserDict.UserDict) : + "jj2" + def __init__(self): + "Warning don't call UserDict.UserDict.__init__()" + print "don't call UserDict.UserDict.__init__()" + +class jj3(jj) : + "jj3" + def __init__(self): + jj.__init__(self) + +class jj4(jj) : + "jj4" + +class A: + 'should not generate warnings' + def __init__(self): pass + +class B(A): + 'should not generate warnings' + +class C(B): + 'should not generate warnings' + def __init__(self): B.__init__(self) --- /dev/null +++ pychecker-0.8.19/test_input/test45.py @@ -0,0 +1,23 @@ +'d' + +__pychecker__ = 'argsused' + +def x(empty, unused): + print 'nothing' +def y(empty1, unused1): + print 'nothing' +def z(): + empty = 1 + unused = 2 + empty1 = 1 + unused1 = 2 + +class A: + 'd' + def x(self, other, empty, unused): + print 'nothing' + def y(self, other1, empty1, unused1): + print 'nothing' + +def a(): + _ = 5 --- /dev/null +++ pychecker-0.8.19/test_input/test86.py @@ -0,0 +1,96 @@ +'warn about raising/catching string exceptions' + +__pychecker__ = 'no-classdoc' + +class g(Exception): pass +h = 'blah' +i = g +j = KeyError +class k: pass + +def f1(a, b, c): + 'should not warn' + class z(Exception): pass + if a: + raise + if a: + raise KeyError + if a: + raise b, '' + if a: + raise c() + if a: + raise g, '' + if a: + raise i + if a: + raise j + if a: + raise z + +def f2(a): + 'should warn' + if a: + raise 'strerr' + if a: + raise h, '' + if a: + raise k + +def f3(a, b, c): + 'should not warn' + class z(Exception): pass + try: + f1(a, b, c) + except a: + pass + except b.bbb: + pass + except KeyError: + pass + except (TypeError, KeyError): + pass + except g: + pass + except z: + pass + except (g, z): + pass + except i, detail: + print detail + except Exception, detail: + print detail + except: + pass + +def f4(a): + 'should warn' + try: + f2(a) + except 'strerr': + pass + except ('strerr1', 'strerr2'): + pass + except ('strerr1', KeyError): + pass + except h: + pass + except k: + pass + +tt = (KeyError, ValueError) + +def f5(a): + 'should not warn' + try: + f2(a) + except tt: + pass + +def f6(a): + 'should not warn' + # but does in 0.8.17 + try: + pass + except KeyboardInterrupt: + pass --- /dev/null +++ pychecker-0.8.19/test_input/test80.py @@ -0,0 +1,25 @@ +'test inconsistent types' + +__pychecker__ = 'changetypes' + +def func1(): + 'should generate a warning' + x = 0 + x += 1.1 + print x + +def func2(): + 'should not generate a warning' + x = "" + x = "string" + for j in []: + x = j + print x + +def func3(): + 'should generate a warning' + y = None + y = [] + y = {} + print y + --- /dev/null +++ pychecker-0.8.19/test_input/test98.py @@ -0,0 +1,33 @@ +# -*- encoding: latin-1 -*- + +__doc__ = 'return value from init reports proper file names' + +from import98 import BaseGood, BaseBad + +class GoodGood(BaseGood): + 'doc' + def __init__(self): + BaseGood.__init__(self) + +class GoodBad(BaseGood): + 'doc' + def __init__(self): + return BaseGood.__init__(self) + +class GoodVoid(BaseGood): + 'doc' + pass + +class BadGood(BaseBad): + 'doc' + def __init__(self): + BaseBad.__init__(self) + +class BadBad(BaseBad): + 'doc' + def __init__(self): + return BaseBad.__init__(self) + +class BadVoid(BaseBad): + 'doc' + pass --- /dev/null +++ pychecker-0.8.19/test_input/test17.py @@ -0,0 +1,35 @@ +'doc' + +class X: + 'should get a warning for returning value from __init__' + def __init__(self): + print 'howdy' + return 1 + +class Y: + 'should get a warning for returning value from __init__' + def __init__(self, x): + if x == 0 : + return 0 + if x == 1 : + return 53 + return None + +class Z: + 'should not get a warning' + def __init__(self, x): + return + + +class Q(Z): + 'd' + def __init__(self): + v = lambda : None + Z.__init__(self, v) + + +class S(Z): + 'd' + def __init__(self): + Z.__init__(self,lambda x: x in ['p','f']) + --- /dev/null +++ pychecker-0.8.19/test_input/test25.py @@ -0,0 +1,16 @@ +'doc' + +import sys + +class A: + 'doc' + z = 1 + def x(self): pass + +def xxx(): + print A.x() + print A.z + print A.a + print A.y() + print sys.lkjsdflksjasdlf + --- /dev/null +++ pychecker-0.8.19/test_input/test57.py @@ -0,0 +1,11 @@ +"doesn't work in 1.5.2" + +def ttt(c): + return None + +def x(): + "should not complain about either, we can't check # args" + columns = [ 1, 2 ] + print zip(*columns) + print ttt(*columns) + --- /dev/null +++ pychecker-0.8.19/test_input/test5.py @@ -0,0 +1,20 @@ +'test named args' +__pychecker__ = 'namedargs' + +def x(a, b, c = None, d = None, **kw): + pass + +def y(): + x(1, 2, c=3, d=4, e=5) + +def z(): + x(1, 2, e=5, d=4) + +class X: + "doc" + def __init__(self): + self.y = 0 + def z(self): + "this should not have any warnings" + x(self.y, { 'a': 'b' }) + --- /dev/null +++ pychecker-0.8.19/test_input/__init__.py @@ -0,0 +1,3 @@ +""" +Tests for PyChecker +""" --- /dev/null +++ pychecker-0.8.19/test_input/test74.py @@ -0,0 +1,41 @@ +'test __getattr[ibute]__ returning None' + +class A: + 'no warning' + def __getattr__(self, attr): + return attr + +class B: + 'no warning' + def __getattribute__(self, attr): + return attr + +class C: + 'warning' + def __getattr__(self, attr): + pass + +class D: + 'warning' + def __getattribute__(self, attr): + pass + +class E: + 'warning' + def __getattr__(self, attr): + if attr == 'n': + return attr + if attr != 'j': + raise AttributeError + +class F: + 'no warning' + def __getattr__(self, attr): + if attr == 'n': + return attr + raise AttributeError + +class G: + 'should not gen a warning' + def __getattr__(self, name): + return getattr(self, 'a')[name] --- /dev/null +++ pychecker-0.8.19/test_input/test87.py @@ -0,0 +1,56 @@ +'test use of True/False' + +True = 1 +False = 0 + +true = 1 +false = 0 + +TRUE = 1 +FALSE = 0 + +def x(a): + 'should warn' + if a == TRUE: + print 'True' + if a == TRUE or \ + a == True or \ + a == true: + print 'True' + if a != false: + print 'false' + if a is 'false': + print 'false' + if a is 'True': + print 'True' + if a is 53343: + print '53343' + if a is 1e7: + print '1e7' + if a is not 'false': + print 'false' + if a is not 'True': + print 'True' + if a is not 53343: + print '53343' + if a is not 1e7: + print '1e7' + +def y(a): + 'should not warn' + if a is True: + print 'True' + if a is not false: + print 'false' + if a == 53343: + print '53343' + if a == 1e7: + print '1e7' + if a == 'TRUE' or \ + a == 'True' or \ + a == 'true': + print 'True' + +def z(a): + return True + --- /dev/null +++ pychecker-0.8.19/test_input/test14.py @@ -0,0 +1,24 @@ +"doesn't work in 1.5.2" + +import string +import string as nn + +used = '' +_unused = 0 + +def yyy(): + import string as jj + +if nn.lower('aa') == '': + pass +if string.lower(used) == '': + pass + +if 1 : + _noglobal = 0 + +import xml.sax as sax + +def zzz(): + print sax + --- /dev/null +++ pychecker-0.8.19/test_input/test82.py @@ -0,0 +1,18 @@ +'test private globals in a class, from tom culliton' + +_happy_private_name=("eyes", "nose", "fingers", "toes") +__unhappy_private_name=("missing life", "long commute", "dumb user") + +def whatsit(thingee): + if (thingee in _happy_private_name + or thingee in __unhappy_private_name): + return "I got one too!" + else: + return "Ooo! What's that?" + +class geek: + 'd' + def __init__(self): + self.happy = _happy_private_name + self.unhappy = __unhappy_private_name + --- /dev/null +++ pychecker-0.8.19/test_input/test50.py @@ -0,0 +1,21 @@ +'d' + +__pychecker__ = 'maxargs=4 maxlocals=3' + +def A(a, b, c): pass +def B(a, b, c, d): pass +def C(a, b, c, d, e): pass +def D(a, b, c, d, f, g): pass + +def E(a, b, c, d): + w = x = y = 0 + print a, b, c, d, w, x, y + +def F(a, b, c, d): + w = x = y = z = 0 + print a, b, c, d, w, x, y, z + +def G(a, b, c, d): + w = x = y = z = jj = 0 + print a, b, c, d, w, x, y, z, jj + --- /dev/null +++ pychecker-0.8.19/test_input/test38.py @@ -0,0 +1,54 @@ +'d' + +class X: + 'd' + def m1(self, a, b, c, d): pass + def m2(self, a, b, c, d, *args): pass + def m3(self, a, b, c, d, *args, **kwArgs): pass + def m4(self, a, b=0, c=0, d=0): pass + def m5(self, a, b=0, c=0, d=0, *args): pass + def m6(self, a, b=0, c=0, d=0, *args, **kwArgs): pass + +class Y1(X): + 'should not generate any warnings' + def m1(self, a, b, c, d): exec a in globals() + def m2(self, a, b, c, d, *args): exec a in globals() + def m3(self, a, b, c, d, *args, **kwArgs): exec a in globals() + def m4(self, a, b, c, d): exec a in globals() + def m5(self, a, b, c, d, *args): exec a in globals() + def m6(self, a, b, c, d, *args, **kwArgs): exec a in globals() + +class Z1(X): + 'should generate warnings' + def m1(self, a, b, c): pass + def m2(self, a, b, c, d): pass + def m3(self, a, b, c, d, **kwArgs): pass + def m4(self, a, b=0, c=0): pass + def m5(self, a, b=0, c=0, d=0): pass + def m6(self, a, b=0, c=0, d=0, **kwArgs): pass + +class Z2(X): + 'should generate warnings' + def m3(self, a, b, c, d, *args): pass + def m6(self, a, b=0, c=0, d=0, *args): pass + +class Z3(X): + 'should generate warnings' + def m3(self, a, b, c, d): pass + def m6(self, a, b=0, c=0, d=0): pass + +class Z4(X): + 'should generate warnings' + def m1(self): pass + def m2(self): pass + def m3(self): pass + def m4(self): pass + def m5(self): pass + def m6(self): pass + +class AAA: + 'should generate 1 warning' + __pychecker__ = 'exec' + def m1(self, a, b, c, d): pass + def m2(self, a, b, c, d, *args): exec a in d + def m3(self, a, b, c, d, *args): exec a --- /dev/null +++ pychecker-0.8.19/test_input/test3.py @@ -0,0 +1,14 @@ + +"Shouldn't be any warnings/errors" + +import string + +def describeSyntax(syntax): + return string.join(['<%s>' % x.Description]) + +from UserDict import UserDict + +class jj(UserDict) : + def __init__(self): + UserDict.__init__(self) + --- /dev/null +++ pychecker-0.8.19/test_input/test31.py @@ -0,0 +1,38 @@ +'doc' + +class X: + 'doc' + +class Y(X): + 'doc' + +class Z(X): + 'doc' + def __init__(self, arg): + pass + +def x(): + 'should not cause a warning' + print X() + print Y() + print Z('should create a warning since no __init__()') + +def y(): + print X(a='should create a warning since no __init__()') + print X('should create a warning since no __init__()') + print Y(a='should create a warning since no __init__()') + print Y('should create a warning since no __init__()') + print Z(1, a='should create a warning since no __init__()') + print Z(1, 2) + +class A: + 'd' + def a(self, a, b, c): pass + def x(self, a, b, c): pass + +class B(A): + 'd' + def y(self): + A.x(self, 1, 2, 3) + def z(self): + A.a(self, 1, 2, 3) --- /dev/null +++ pychecker-0.8.19/test_input/test102.py @@ -0,0 +1,16 @@ + +"""This used to be a problem for code that assumed __bases__ existed.""" + +class GetattrReturnsNone(object): + """This requires a new-style class.""" + def __getattr__(self, unused_name): + return None + +dummy1 = GetattrReturnsNone() + +class GetattrReturnsStr(object): + """This requires a new-style class.""" + def __getattr__(self, unused_name): + return 'abc' + +dummy2 = GetattrReturnsStr() --- /dev/null +++ pychecker-0.8.19/test_input/test49.py @@ -0,0 +1,37 @@ +'d' + +def x(): + d = e = 7 + print d / e + print d / 3 + print 7 / e + print 5 / 6 + +def y1(): + x = 0 + return (x * 100.0) / 10 + +def y2(): + x = 0 + return (x + 100.0) / 10 + +def y3(): + x = 0 + return (x - 100.0) / 10 + +def y4(): + x = 1 + return (x ** 100.0) / 10 + +def z(e): + x = 0 + if e: + x = x + 1 + return (x * 100.0) / 10 + y = 0 + return (x * 100.0) / y + +def should_not_warn(a): + # this warning should be suppressed automatically + x = int(a) + return int(x / 5) --- /dev/null +++ pychecker-0.8.19/test_input/test76.py @@ -0,0 +1,12 @@ +'test 3+ nested functions' + +__pychecker__ = 'argsused' + +def x(a=1): + def y(b=2, c=3, d=4): + def z(b=2, e=5): + print 'in z', b, e + print 'in y', b, c + z() + print 'in x' + y() --- /dev/null +++ pychecker-0.8.19/test_input/test97.py @@ -0,0 +1,20 @@ +# -*- encoding: latin-1 -*- + +__doc__ = 'nested scopes test' + +u"Blåbærgrød".upper() + +try: + from cStringIO import StringIO +except ImportError: + # this shouldn't cause a warning about catching string exceptions + pass + +def call(proc, y): + proc(y) + +def fun(): + def setfooattr(x, y): + call(lambda z: setattr(x, 'foo', z), y) + + setfooattr(Exception(), 'bar') --- /dev/null +++ pychecker-0.8.19/test_input/test32.py @@ -0,0 +1,16 @@ +'doc' + +class X: + 'doc' + def __init__(self): pass + +class Y(X): + 'doc' + def __init__(self, s): + X.__init__(s) + +class Z(X): + 'doc' + def __init__(self, s): + X.__init__() + --- /dev/null +++ pychecker-0.8.19/test_input/test52.py @@ -0,0 +1,54 @@ +"doesn't work in 1.5.2" + +class foo: + 'd' + def __init__(self, *args, **kwargs): + self.args = args + self.kw = kwargs + +class foo2(foo): + 'd' + def __init__(self, *args): + foo.__init__(self, jj=5, kk=10, *args) + +class foo3(foo): + 'd' + def __init__(self, **kwargs): + foo.__init__(self, jj=5, kk=10, **kwargs) + +class foo4(foo): + 'd' + def __init__(self, *args, **kwargs): + foo.__init__(self, jj=5, kk=10, *args, **kwargs) + +class c: + 'd' + def __init__(self): + pass + +class c1: + 'd' + o = c() + def c(self,x): + print x + +def x(): + a = c1() + a.b = c1() + # we can't handle this yet + # a.b.c(5) + +class c2: + 'd' + def m1(self): + print "ok" + def m2(self,x): + print "ok" + +class c3: + 'd' + c2 = None + def m(self): + self.c2.m1() + self.c2.m2(5) + --- /dev/null +++ pychecker-0.8.19/test_input/test92.py @@ -0,0 +1,6 @@ +'''test using locals in module scope works and there are no spurious warnings''' + +w = '%(u)s' +u = 'a' +result = w % locals() + --- /dev/null +++ pychecker-0.8.19/test_input/test89.py @@ -0,0 +1,8 @@ +'doc' + +class Newbie(object): + '''__coerce__ is problematic in new style classes, + see http://python.org/sf/547211 + ''' + def __coerce__(self, o): pass + --- /dev/null +++ pychecker-0.8.19/test_input/test58.py @@ -0,0 +1,11 @@ +'Note: this will only work on Python 2.1 and before' + +yield = None + +def x(): + yield = 53 + print yield + +def y(): + print yield + --- /dev/null +++ pychecker-0.8.19/test_input/test83.py @@ -0,0 +1,43 @@ +'test unpacking variables' + +def func1(): + 'should not warn' + x, z = (5, 2) + +def func2(): + 'should warn' + x, y, z = (5, 2) + +def func3(): + 'should warn' + a = (5, 2) + x, y, z = a + +def func4(): + 'should warn' + x, = (5, 2) + +def func5(): + 'should warn' + x, y = 5, + +def func6(): + 'should warn' + x, = 5 + +def func101(): + 'should not warn' + x, y, z = (5, 2, 3, 4, 5)[:3] + +def func102(): + 'should warn ideally, but size becomes unknown' + x, y, z = (5, 2, 3, 4, 5)[:2] + +def func103(): + 'should not warn' + x, y, z = (5, 2, 3, 4, 5)[2:] + +def func104(): + 'should warn ideally, but size becomes unknown' + x, y, z = (5, 2, 3, 4, 5)[3:] + --- /dev/null +++ pychecker-0.8.19/test_input/pycheckrc @@ -0,0 +1,7 @@ + +suppressions = { 'test39': 'no-moduledoc', 'test39.func2': 'funcdoc', + 'test39.X1': 'no-classdoc', 'test39.X2.x': 'self="s"' } + +suppressionRegexs = { 'test39.Y.': 'no-classdoc', + 'test39.Y..a': 'funcdoc', + 'test39.NewStyle.f': 'no-local' } --- /dev/null +++ pychecker-0.8.19/test_input/test41.py @@ -0,0 +1,18 @@ +'d' + +def x(): pass +def x(): pass + +class X: + 'first use okay' +class X: + 'reuse not okay' + +class Y: + 'should warning about x being redefined' + def x(self): pass + def x(self): pass + +class Z: + 'should not be a warning' + def x(self): pass --- /dev/null +++ pychecker-0.8.19/test_input/test40.py @@ -0,0 +1,34 @@ +'d' + +__pychecker__ = 'argsused' + +def x0(): + print 'should be ok' + +def x1(a, b, c, *args, **kw): + print a, b, c + +def x2(a, b, c, *args, **kw): + print a, b, c, args + +def x3(a, b, c, *args, **kw): + print a, b, c, args, kw + +def x4(a, b, c, *args, **kw): + print 'uh-oh, forgot to use args' + +def x5(a, b, c, *args, **kw): + raise NotImplementedError + +def x6(a, b, c, *args, **kw): + pass + +def x7(a, b, c, *args, **kw): + return None + +class X: + 'd' + def x1(self): + print 'hi' + def x2(self, a, *args, **kw): + print 'oops' --- /dev/null +++ pychecker-0.8.19/test_input/test39.py @@ -0,0 +1,44 @@ + +def func1(): pass +def func2(): pass + +class X1: + def x(self) : pass + def y(self) : pass + +class X2: + def x(self) : pass + def y(self) : pass + +class Y1: + def a(self) : pass + def x(self) : pass + def y(self) : pass + +class Y2: + def a(self) : pass + def x(self) : pass + def y(self) : pass + +class check_here: + 'test __pychecker__ var at class scope' + __pychecker__ = 'funcdoc argsused unusednames=foo,bar' + def a(self) : + 'd' + pass + def x(self, foo) : + print self + def y(self, bar) : + print self + def z(self, jjj) : + j = 0 + +# Requires Python 2.2+ +try: + class NewStyle(object): + 'test that suppressions work with new style classes' + def f(self): + i = 5 + +except NameError: + pass --- /dev/null +++ pychecker-0.8.19/test_input/test42.py @@ -0,0 +1,16 @@ +'d' + +import sys + +def x(): + print sys.ps1 + print sys.ps2 + print sys.tracebacklimit + print sys.exc_type + print sys.exc_value + print sys.exc_traceback + print sys.last_type + print sys.last_value + print sys.last_traceback + print sys.__dict__ + --- /dev/null +++ pychecker-0.8.19/test_input/import47.py @@ -0,0 +1,7 @@ +'d' + +class import47: + 'this class must be named the same as the file to create a spurious warning' + v = 'n' + def print_version(self): + print import47.v --- /dev/null +++ pychecker-0.8.19/test_input/import56a.py @@ -0,0 +1,9 @@ +'doc' + +from import56b import Bar + +class Foo(Bar): + 'doc' + def __init__(self): + Bar.__init__(self) + --- /dev/null +++ pychecker-0.8.19/test_input/test29.py @@ -0,0 +1,14 @@ +'doc' + +import fnmatch + +class X: + 'doc' + def x(self): + x = filter(lambda f, p = '' : fnmatch.fnmatch(f, p), []) + print x + +def x(cpu): + p = len(filter(lambda x: x.find('processor') > -1, cpu.items)) + print p + --- /dev/null +++ pychecker-0.8.19/test_input/test79.py @@ -0,0 +1,33 @@ +'test iterating over a string' + +__pychecker__ = 'stringiter' + +def func1(): + 'should generate a warning' + s = 'string' + for c in s: + print 'oops', c[0] + +def func2(): + 'should generate a warning' + f = open('/dev/null') + s = f.read() + for c in s: + print 'oops', c[0] + +def func3(): + 'should not generate a warning' + for i in []: + print 'ok', i + for i in (): + print 'ok', i + +def func4(): + 'should not generate a warning' + v = [] + for i in v: + print 'ok', i + w = () + for i in w: + print 'ok', i + --- /dev/null +++ pychecker-0.8.19/test_input/test53.py @@ -0,0 +1,28 @@ +'d' + +def x(): + # these are broken, this is BAD code!!! + i = ~~ (10) + while i > 0 : + --i + while i < 100 : + ++i + + # these are fine + j = 0 + while j > 0 : + j = j - 1 + while j < 100 : + j = j + 1 + +def y(): + # should not generate a warning + print ("format w/2 strings %s" + "=" + "'%s'") % ('a', 'b') + # should generate a warning + print ("format w/2 strings %s" + "=" + "'%s'") % ('a', 'b', 'c') + +def z(): + i = -5 + print +i, i, -i + print +5, 5, -5 + --- /dev/null +++ pychecker-0.8.19/test_input/import98.py @@ -0,0 +1,11 @@ +__doc__ = 'Auxiliary file for test98.py' + +class BaseGood: + 'Nice base init' + def __init__(self): + return + +class BaseBad: + 'Error should print as coming from this file' + def __init__(self): + return 42 --- /dev/null +++ pychecker-0.8.19/test_input/test9.py @@ -0,0 +1,17 @@ + +"doc" + +import getopt + +def func(): + "re-importing getopt should complain" + import getopt + print getopt + +def test(): + "this should fail (there is no getopt.xyz)" + try: + print "" + except getopt.xyz: + pass + --- /dev/null +++ pychecker-0.8.19/test_input/test16.py @@ -0,0 +1,19 @@ +"doc" + +import re +import sys +import glob + +class X: + 'doc' + global_var = re.compile('a') + def m(self, j = re.match): + print X.global_var + + def xxx(self, j = glob.glob): + print j + +def xxx(j = sys.path): + print j + + --- /dev/null +++ pychecker-0.8.19/test_input/test94.py @@ -0,0 +1,54 @@ +'docstring' + +def f(a): + a = a + a.b = a.b + a.b.c = a.b.c + a.b.c.d = a.b.c.d + c = a & a + c = a | a + c = a.b | a.b + c = a.b.c | a.b.c + c = a ^ a + c = a.b ^ a.b + c = a.b.c ^ a.b.c + c = a / a + print c + +def g(): + a = b = c = 1 + a = a / 2.0 + a /= 2.0 + a = a + b + a = a & b + a = a << b + a = b << a + print c + a = str(a) + a = `a` + a = -a + a = ~a + +def h(): + a = 1 + a += a + a -= a + a *= a + + a = not a + a = not not a + + a = (1, 2, 3) + a, b, c = a + +def i(a): + z = hash(a.x) & hash(a.y) + z = hash(a.x) | hash(a.y) + z = hash(a.x) ^ hash(a.y) + return z + +def j(x, y): + return (x + 1.0) / (y + 2.0) + +def k(d): + return ((1 << d) | (1 << ((d+4) % 8))) --- /dev/null +++ pychecker-0.8.19/test_input/test64.py @@ -0,0 +1,17 @@ +'''spurious warnings reported by Andrew Dalke +''' + +import sys, string, re +import array + +class _Anything: pass +_anything = _Anything() + +def outer(): + def x(): + return _anything + + def y(): + return dir(string.translate) + + x() --- /dev/null +++ pychecker-0.8.19/test_input/test81.py @@ -0,0 +1,30 @@ +'test use of freevars and cellvars' + +from __future__ import nested_scopes + +__pychecker__ = 'classattr' + +class Board: + 'base class to test' + def atomCount(self): + pass + +def func(l): + pass + +class BoardTests: + 'should not generate a warning' + def testAddAtom(self): + b = Board() + b.atomCount() + func(lambda:b.atomCount()) + +def q(funcp): + print funcp() + +def f(): + y = 1 + def g(): + return y + q(g) + --- /dev/null +++ pychecker-0.8.19/test_input/test61.py @@ -0,0 +1,28 @@ +'d' + +class X: + 'd' + def x(self, g, h): pass + +def y(): + x = X() + print x.x() + +def z(): + x = X() + print x.x(1, 2) + +def a(): + d = {} + print d.get(1, 5) + print d.get(1, 5, 7) + print d.keys() + print d.keys(1, 5, 7) + print d.clear() + x = d.clear() + x.y = d.clear() + d.clear() + print + print setattr(d, 'junk', 'neal') + print `d`.rjust(5) + --- /dev/null +++ pychecker-0.8.19/test_input/test2.py @@ -0,0 +1,20 @@ + +"time module not used if write32u() line in X.uuu() is commented out" + +import time + +def write32u(a, b): pass + +class X: + def __init__(self): + self.fileobj = 0 + def uuu(self): + #write32u(self.fileobj, long(time.time())) + return None + +class Y(X): + def __init__(self) : + "ERROR: X.__init__() isn't called" + # X.__init__(self) + self.x = 0 + --- /dev/null +++ pychecker-0.8.19/test_input/test101.py @@ -0,0 +1,33 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# see https://sourceforge.net/tracker/index.php?func=detail&aid=1563495&group_id=24686&atid=382217 + +'d' + +__pychecker__ = 'blacklist=wrongname' + +import os +import imp +import tempfile + +code = """ +class C: + pass + +c = C() +""" + +# create a temporary file for the module +(fd, path) = tempfile.mkstemp() +os.write(fd, code) +os.close(fd) + +temp = imp.load_source('temp', path) + +# change class's module to trigger the error +temp.C.__module__ = 'wrongname' + +# clean up +os.unlink(path) + --- /dev/null +++ pychecker-0.8.19/test_input/test56.py @@ -0,0 +1,7 @@ +'doc' + +from import56a import Foo + +def x(): + print Foo + --- /dev/null +++ pychecker-0.8.19/test_input/test23.py @@ -0,0 +1,48 @@ +'doc' + +class X: + 'doc' + def __init__(self): + self.fff = 0 + + def x(self): + pass + + def y(self): + 'should generate a warning' + if self.x: + pass + if self.x and globals(): + pass + if globals() and self.x: + pass + + def z(self): + 'should NOT generate a warning' + if globals() : + pass + if self.x() and self.fff: + pass + if self.x() and globals(): + pass + if globals() and self.x(): + pass + if self.fff: + pass + print self.x + print self.fff + +class Y(X): + 'doc' + def j(self): + 'should generate a warning' + if self.x: + pass + print self.fff + + def h(self): + 'should NOT generate a warning' + if self.x(): + pass + print self.x + print self.fff --- /dev/null +++ pychecker-0.8.19/test_input/test30.py @@ -0,0 +1,8 @@ +'doc' + +import fnmatch + +def x(): + x = filter(lambda f, p = '' : fnmatch.fnmatch(f, p), []) + print x + --- /dev/null +++ pychecker-0.8.19/test_input/test62.py @@ -0,0 +1,4 @@ +'bug found by Joe VanAndel' + +isintorlong = lambda x: type(x) == type(0) or type(x) == type(0L) + --- /dev/null +++ pychecker-0.8.19/test_input/test88.py @@ -0,0 +1,29 @@ +''' +test depreacted modules (and functions in modules) +also test functions w/security implications +''' + +import os + +# gopherlib was removed in 2.6 +try: + import gopherlib +except ImportError: + pass + +import string + +try: + import whrandom +except ImportError: + pass + +def t1(): + 'get rid of warnings about not using deprecated modules' + print whrandom, gopherlib + +def t2(): + print os.tempnam() + print os.tmpnam() + print os.name + print string.atof('5') --- /dev/null +++ pychecker-0.8.19/test_input/test27.py @@ -0,0 +1,15 @@ +'doc' + +import fnmatch + +x = [] +bfp = '' +x = filter(lambda f, p = bfp : fnmatch.fnmatch(f, p), x) + +def y(): + print x + +def d(lines): + import string + lines = map(lambda s: string.strip(s), lines) + --- /dev/null +++ pychecker-0.8.19/test_input/import69.py @@ -0,0 +1,8 @@ +'d' + +class Test: + 'd' + def __init__(self): pass + +class Alias(Test): + 'd' --- /dev/null +++ pychecker-0.8.19/test_input/test13.py @@ -0,0 +1,30 @@ + +"global test" + +def test1(): + 'without -g option, this should be the only warning for x' + global x + x = 90 + +def test2(): + 'with -g option, this should be also generate a warning for x' + global x + x = 90 + +def test3(): + 'with -g option, this should be also generate a warning for x' + global x + x = 90 + +def test4(): + 'without -g option, this should be the only warning for xxx' + print xxx + +def test5(): + 'with -g option, this should be also generate a warning for xxx' + print xxx + +def test6(): + 'with -g option, this should be also generate a warning for xxx' + print xxx + --- /dev/null +++ pychecker-0.8.19/test_input/test63.py @@ -0,0 +1,15 @@ +'d' + +def x(v): + count = 0 + if v != 0: + return 1 + return count + +def y(v): + x = len(v) + if x == 0 : + return x + else : + return x - 1 + --- /dev/null +++ pychecker-0.8.19/test_input/test99.py @@ -0,0 +1,22 @@ +"""None of these should blow up.""" + +class Foo: + """Base class to call during test""" + def __init__(self, *args, **kwargs): pass + +A = B = C = D = 1 + +class AndBar(Foo): + """Base class to call during test""" + def __init__(self): + Foo.__init__(self, style = A & B & C & D) + +class OrBar(Foo): + """Base class to call during test""" + def __init__(self): + Foo.__init__(self, style = A | B | C | D) + +class XorBar(Foo): + """Base class to call during test""" + def __init__(self): + Foo.__init__(self, style = A ^ B ^ C ^ D) --- /dev/null +++ pychecker-0.8.19/test_input/test7.py @@ -0,0 +1,18 @@ + +"doc" + +def func(): pass + +class X: + "should only generate a warning w/-A, --callattr cmd line options" + def __init__(self, other): + self.func = func + self.other = other + self.x = None + + def test(self): + "self.y should generate a function" + self.func() + self.other() + self.x() + self.y() --- /dev/null +++ pychecker-0.8.19/test_input/test95.py @@ -0,0 +1,5 @@ +'docstring' + +def try_uni(): + word = "a" + return u"%s \N{RIGHTWARDS ARROW}" % word --- /dev/null +++ pychecker-0.8.19/test_input/test55.py @@ -0,0 +1,47 @@ +'d' + +def x(): + try : + print "howdy, this ain't right" + except KeyError, RuntimeError : + pass + +def y(): + try : + print "ok, " + "this func %s should be fine" % y.__name__ + except (KeyError, RuntimeError) : + pass + +def z(): + try : + pass + except (KeyError, RuntimeError, IndexError) : + pass + +def a(): + try : + pass + except (KeyError, RuntimeError, IndexError), a : + print a + +try : + pass +except KeyError, RuntimeError : + pass + +try : + pass +except (KeyError, RuntimeError) : + pass + +def b(): + try : + print "ok, " + "this func %s should be fine" % y.__name__ + except (KeyError, RuntimeError), msg : + print msg +def c(): + try : + print "ok, " + "this func %s should be fine" % y.__name__ + except KeyError, detail : + print detail + --- /dev/null +++ pychecker-0.8.19/test_input/test11.py @@ -0,0 +1,20 @@ +"doc" + +class Test: + "'No attribute (alias) found' warning should not be generated" + + def __init__(self): + self.alias() + + def real(self): + pass + + alias = real + + +def rcParseTest(a = 10, b = 'ten', c = (5, 5)): + print '%s, %s, %s' % (a, b, str(c)) + +def a(i): + [0, 1, 3].index(i) + --- /dev/null +++ pychecker-0.8.19/test_input/test8.py @@ -0,0 +1,4 @@ +"doc" + +def func(): + syntax error here --- /dev/null +++ pychecker-0.8.19/test_input/test26.py @@ -0,0 +1,11 @@ +"" +class Foo: + "" + def __init__(self,q): + print q + +class Bar(Foo): + "" + def __init__(self): + Foo.__init__(self,{ 'a' : 1 }) + --- /dev/null +++ pychecker-0.8.19/test_input/test72.py @@ -0,0 +1,29 @@ +'test setting class attributes not in __init__ w/initattr set' + +__pychecker__ = 'initattr no-classdoc' + +class A: + 'd' + def a(self): + self.y = 0 + +class B(A): + 'd' + def b(self): + self.z = 0 + +class C: + 'd' + def __init__(self): + self.a = self.b = self.c = 0 + self.d = None + self.e = [] + + def b(self): + print self.z + self.y = 0 + +class D(C): + def c(self): + self.a = 5 + --- /dev/null +++ pychecker-0.8.19/test/common.py @@ -0,0 +1,100 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +import os +import commands + +# use twisted if we can so we get nice trial goodness +try: + from twisted.trial import unittest +except ImportError: + import unittest + +def canImport(module): + ''' + Check if we can import the given module name. + + @type module: str + + @rtype: bool + ''' + try: + __import__(module) + return True + except ImportError: + return False + +# lifted from flumotion with permission +def _diff(old, new, desc): + import difflib + lines = difflib.unified_diff(old, new) + lines = list(lines) + if not lines: + return + output = '' + for line in lines: + output += '%s: %s\n' % (desc, line[:-1]) + + raise AssertionError( + ("\nError while comparing strings:\n" + "%s") % (output,)) + +def diffStrings(orig, new, desc='input'): + def tolines(s): + return [line + '\n' for line in s.split('\n')] + + return _diff(tolines(orig), tolines(new), desc=desc) + + +# our base class for all tests +class TestCase(unittest.TestCase): + def check(self, testname, args=''): + """ + Run pychecker on the given test, located in input/ + Will compare to output of the same name in expected/ + """ + return self.checkMultiple(testname, [testname + '.py'], args) + + def checkMultiple(self, testname, checkables, args=''): + """ + Run pychecker on the given test, located in input/ + Will compare to output of the same name in expected/ + + @type args: str + @type checkables: list of str + """ + abstestdir = os.path.dirname(__file__) + abspycheckerdir = os.path.dirname(abstestdir) + + # make this relative to where we are, so paths shown are relative too + #if abstestdir.startswith(os.getcwd()): + # abstestdir = abstestdir[len(os.getcwd()) + 1:] + + pycheckerpy = os.path.join(abspycheckerdir, 'pychecker', 'checker.py') + testfiles = [os.path.join('input', c) for c in checkables] + + cmd = "cd %s; python -tt %s " \ + "--limit 0 --no-argsused " \ + "%s %s" % (abstestdir, pycheckerpy, args, " ".join(testfiles)) + # getoutput output never ends on a newline the way + # pychecker ... > expected/... would + output = commands.getoutput(cmd) + '\n' + + # here we can select a different file based on os/python version/arch + relexpectedfile = os.path.join('expected', testname) + if args: + underscoredArgs = args.replace('-', '_').replace(' ', '_') + relexpectedfile += underscoredArgs + absexpectedfile = os.path.join(abstestdir, relexpectedfile) + + # FIXME: make generating an option + # for now, do it every time we don't have the expected output + # to help us + if not os.path.exists(absexpectedfile): + open(absexpectedfile, 'w').write(output) + print 'Generated non-existing output file', absexpectedfile + + expected = open(absexpectedfile).read() + + diffStrings(expected, output, desc=relexpectedfile) + --- /dev/null +++ pychecker-0.8.19/test/main.py @@ -0,0 +1,15 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# import all TestCase from all test modules +# FIXME: we could autodiscovery all test_ modules +# note: this means all TestCase classes need a different name, might +# be a problem if one shadows another accidentally ? + +from test_stdlib import * +from test_module import * +from test_dict import * +from test_pychecker_CodeChecks import * + +if __name__ == '__main__': + unittest.main() --- /dev/null +++ pychecker-0.8.19/test/input/test_nestedsuppression.py @@ -0,0 +1,65 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +class O(object): + pass + +def containerFirst(): + def first(): + __pychecker__ = 'no-objattrs' + a = O() + # this one should not trigger a warning since __pychecker__ hides it + print a.nonexistent + + def second(): + b = O() + # this one should trigger a warning + print b.nonexistent + + first() + second() + +def containerSecond(): + def first(): + a = O() + # this one should trigger a warning + print a.nonexistent + + def second(): + __pychecker__ = 'no-objattrs' + b = O() + # this one should not trigger a warning since __pychecker__ hides it + print b.nonexistent + + first() + second() + +def containerNeither(): + def first(): + a = O() + # this one should trigger a warning + print a.nonexistent + + def second(): + b = O() + # this one should trigger a warning + print b.nonexistent + + first() + second() + +def containerBoth(): + def first(): + __pychecker__ = 'no-objattrs' + a = O() + # this one should not trigger a warning since __pychecker__ hides it + print a.nonexistent + + def second(): + __pychecker__ = 'no-objattrs' + b = O() + # this one should not trigger a warning since __pychecker__ hides it + print b.nonexistent + + first() + second() --- /dev/null +++ pychecker-0.8.19/test/input/test_global.py @@ -0,0 +1,30 @@ +"global test - test13" + + +def test1(): + 'without -g option, this should be the only warning for x' + global x + x = 90 + +def test2(): + 'with -g option, this should be also generate a warning for x' + global x + x = 90 + +def test3(): + 'with -g option, this should be also generate a warning for x' + global x + x = 90 + +def test4(): + 'without -g option, this should be the only warning for xxx' + print xxx + +def test5(): + 'with -g option, this should be also generate a warning for xxx' + print xxx + +def test6(): + 'with -g option, this should be also generate a warning for xxx' + print xxx + --- /dev/null +++ pychecker-0.8.19/test/input/test_getmodule.py @@ -0,0 +1,5 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from getmodule.A import C as one +from getmodule.B import C as two --- /dev/null +++ pychecker-0.8.19/test/input/test_STORE_SLICE_PLUS_0.py @@ -0,0 +1,10 @@ +# -*- Mode: Python; test-case-name: test.test_pychecker_CodeChecks -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# abridged version of twisted.trial.unittest.TestCase which triggered +# unimplemented opcode 40 +class TestCase: + _warnings = None + + def flushWarnings(self): + self._warnings[:] = [] --- /dev/null +++ pychecker-0.8.19/test/input/test_zope_interface.py @@ -0,0 +1,4 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from zope.interface import Interface --- /dev/null +++ pychecker-0.8.19/test/input/test_DUP_TOPX.py @@ -0,0 +1,14 @@ +# -*- Mode: Python; test-case-name: test.test_pychecker_CodeChecks -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# trigger opcode 99, DUP_TOPX + +def duptopx(): + d = {} + + for i in range(0, 9): + d[i] = i + + for k in d: + # the += on a dict member triggers DUP_TOPX + d[k] += 1 --- /dev/null +++ pychecker-0.8.19/test/input/test_dict.py @@ -0,0 +1,7 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +# this should be fine, but failed with pychecker 0.8.18 on python 2.6 +def func(): + d = { 'a': 1, 'b': 2} + print d.keys() --- /dev/null +++ pychecker-0.8.19/test/input/test_slice.py @@ -0,0 +1,12 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +def func(): + d = [1, 2, 3] + del d[1:2] + +def func2(): + e = 1 + del e[1:2] + +func2() --- /dev/null +++ pychecker-0.8.19/test/input/getmodule/__init__.py @@ -0,0 +1 @@ +'d' --- /dev/null +++ pychecker-0.8.19/test/input/getmodule/B/C.py @@ -0,0 +1,4 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +import os --- /dev/null +++ pychecker-0.8.19/test/input/getmodule/A/C.py @@ -0,0 +1,4 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +import time --- /dev/null +++ pychecker-0.8.19/test/expected/test_dict @@ -0,0 +1,5 @@ +Processing module test_dict (input/test_dict.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test/expected/test_global_g @@ -0,0 +1,10 @@ +Processing module test_global (input/test_global.py)... + +Warnings... + +input/test_global.py:7: Global variable (x) not defined in module scope +input/test_global.py:12: Global variable (x) not defined in module scope +input/test_global.py:17: Global variable (x) not defined in module scope +input/test_global.py:21: No global (xxx) found +input/test_global.py:25: No global (xxx) found +input/test_global.py:29: No global (xxx) found --- /dev/null +++ pychecker-0.8.19/test/expected/test_zope_interface_q @@ -0,0 +1,5 @@ +Processing module test_zope_interface (input/test_zope_interface.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test/expected/test_global @@ -0,0 +1,6 @@ +Processing module test_global (input/test_global.py)... + +Warnings... + +input/test_global.py:7: Global variable (x) not defined in module scope +input/test_global.py:25: No global (xxx) found --- /dev/null +++ pychecker-0.8.19/test/expected/test_slice @@ -0,0 +1,5 @@ +Processing module test_slice (input/test_slice.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test/expected/test_DUP_TOPX @@ -0,0 +1,5 @@ +Processing module test_DUP_TOPX (input/test_DUP_TOPX.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test/expected/test_STORE_SLICE_PLUS_0 @@ -0,0 +1,5 @@ +Processing module test_STORE_SLICE_PLUS_0 (input/test_STORE_SLICE_PLUS_0.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test/expected/test_getmodule @@ -0,0 +1,8 @@ +Processing module C (input/getmodule/A/C.py)... +Processing module C (input/getmodule/B/C.py)... + +Warnings... + +input/getmodule/A/C.py:4: Imported module (time) not used + +input/getmodule/B/C.py:4: Imported module (os) not used --- /dev/null +++ pychecker-0.8.19/test/expected/test_nestedsuppression__objattrs @@ -0,0 +1,8 @@ +Processing module test_nestedsuppression (input/test_nestedsuppression.py)... + +Warnings... + +input/test_nestedsuppression.py:17: Object (b) has no attribute (nonexistent) +input/test_nestedsuppression.py:26: Object (a) has no attribute (nonexistent) +input/test_nestedsuppression.py:41: Object (a) has no attribute (nonexistent) +input/test_nestedsuppression.py:46: Object (b) has no attribute (nonexistent) --- /dev/null +++ pychecker-0.8.19/test_expected/test3 @@ -0,0 +1,8 @@ +Processing module test3 (test_input/test3.py)... + +Warnings... + +UserDict.py:4: No doc string for class UserDict + +test_input/test3.py:7: No global (x) found +test_input/test3.py:12: No doc string for class jj --- /dev/null +++ pychecker-0.8.19/test_expected/test76 @@ -0,0 +1,6 @@ +Processing module test76 (test_input/test76.py)... + +Warnings... + +test_input/test76.py:7: Parameter (a) not used +test_input/test76.py:7: Parameter (d) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test50 @@ -0,0 +1,8 @@ +Processing module test50 (test_input/test50.py)... + +Warnings... + +test_input/test50.py:7: Function (C) has too many arguments (5) +test_input/test50.py:8: Function (D) has too many arguments (6) +test_input/test50.py:14: Function (F) has too many local variables (4) +test_input/test50.py:18: Function (G) has too many local variables (5) --- /dev/null +++ pychecker-0.8.19/test_expected/test79 @@ -0,0 +1,6 @@ +Processing module test79 (test_input/test79.py)... + +Warnings... + +test_input/test79.py:8: Iterating over a string (s) +test_input/test79.py:15: Iterating over a string (s) --- /dev/null +++ pychecker-0.8.19/test_expected/test48-2.5 @@ -0,0 +1,39 @@ +Processing module test48 (test_input/test48.py)... + +Warnings... + +test_input/test48.py:10: Object (i) has no attribute (has_no_method) +test_input/test48.py:11: Object (l) has no attribute (has_no_method) +test_input/test48.py:12: Object (d) has no attribute (has_no_method) +test_input/test48.py:13: Object (s) has no attribute (has_no_method) +test_input/test48.py:14: Object (n) has no attribute (has_no_method) +test_input/test48.py:15: Object (e) has no attribute (has_no_method) +test_input/test48.py:17: Object (i) has no attribute (has_no_attr) +test_input/test48.py:18: Object (l) has no attribute (has_no_attr) +test_input/test48.py:19: Object (d) has no attribute (has_no_attr) +test_input/test48.py:20: Object (s) has no attribute (has_no_attr) +test_input/test48.py:21: Object (n) has no attribute (has_no_attr) +test_input/test48.py:22: Object (e) has no attribute (has_no_attr) +test_input/test48.py:28: Object (jj) has no attribute (a) +test_input/test48.py:29: Object (jj) has no attribute (b) +test_input/test48.py:46: Object (tt) has no attribute (a) +test_input/test48.py:47: Object (tt) has no attribute (b) +test_input/test48.py:53: Statement appears to have no effect +test_input/test48.py:54: Statement appears to have no effect +test_input/test48.py:55: Statement appears to have no effect +test_input/test48.py:56: Statement appears to have no effect +test_input/test48.py:58: Statement appears to have no effect +test_input/test48.py:59: Statement appears to have no effect +test_input/test48.py:63: Statement appears to have no effect +test_input/test48.py:65: Statement appears to have no effect +test_input/test48.py:66: Statement appears to have no effect +test_input/test48.py:70: Statement appears to have no effect +test_input/test48.py:71: Statement appears to have no effect +test_input/test48.py:72: Statement appears to have no effect +test_input/test48.py:73: Statement appears to have no effect +test_input/test48.py:74: Statement appears to have no effect +test_input/test48.py:75: Statement appears to have no effect +test_input/test48.py:76: Statement appears to have no effect +test_input/test48.py:77: Statement appears to have no effect +test_input/test48.py:78: Statement appears to have no effect +test_input/test48.py:79: Statement appears to have no effect --- /dev/null +++ pychecker-0.8.19/test_expected/test17-2.4 @@ -0,0 +1,7 @@ +Processing module test17 (test_input/test17.py)... + +Warnings... + +test_input/test17.py:7: Cannot return a value from __init__ +test_input/test17.py:13: Cannot return a value from __init__ +test_input/test17.py:15: Cannot return a value from __init__ --- /dev/null +++ pychecker-0.8.19/test_expected/test90 @@ -0,0 +1,16 @@ +Processing module test90 (test_input/test90.py)... + +Warnings... + +test_input/test90.py:4: Using is 1, may not always work +test_input/test90.py:5: Using is s, may not always work +test_input/test90.py:6: Using is 1.32, may not always work +test_input/test90.py:7: Using is (), may not always work +test_input/test90.py:8: Using is [], may not always work +test_input/test90.py:9: Using is {}, may not always work +test_input/test90.py:14: Using is not 1, may not always work +test_input/test90.py:15: Using is not s, may not always work +test_input/test90.py:16: Using is not 1.32, may not always work +test_input/test90.py:17: Using is not (), may not always work +test_input/test90.py:18: Using is not [], may not always work +test_input/test90.py:19: Using is not {}, may not always work --- /dev/null +++ pychecker-0.8.19/test_expected/test94 @@ -0,0 +1,16 @@ +Processing module test94 (test_input/test94.py)... + +Warnings... + +test_input/test94.py:4: Setting a to itself has no effect +test_input/test94.py:5: Setting a.b to itself has no effect +test_input/test94.py:6: Setting a.b.c to itself has no effect +test_input/test94.py:7: Setting a.b.c.d to itself has no effect +test_input/test94.py:8: a & a has no effect +test_input/test94.py:9: a | a has no effect +test_input/test94.py:10: a.b | a.b has no effect +test_input/test94.py:11: a.b.c | a.b.c has no effect +test_input/test94.py:12: a ^ a is always 0 +test_input/test94.py:13: a.b ^ a.b is always 0 +test_input/test94.py:14: a.b.c ^ a.b.c is always 0 +test_input/test94.py:15: a / a is always 1 or ZeroDivisionError --- /dev/null +++ pychecker-0.8.19/test_expected/test89-2.2 @@ -0,0 +1,5 @@ +Processing module test89 (test_input/test89.py)... + +Warnings... + +test_input/test89.py:7: Using __coerce__ in new-style class (Newbie) will not work for binary operations --- /dev/null +++ pychecker-0.8.19/test_expected/test74-2.4 @@ -0,0 +1,10 @@ +Processing module test74 (test_input/test74.py)... + +Warnings... + +test_input/test74.py:10: Using __getattribute__ in old-style class (B) does not work +test_input/test74.py:17: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:20: Using __getattribute__ in old-style class (D) does not work +test_input/test74.py:22: __getattribute__ should not return None, raise an exception if not found +test_input/test74.py:30: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:41: Passing a constant string to getattr, consider direct reference --- /dev/null +++ pychecker-0.8.19/test_expected/test48 @@ -0,0 +1,40 @@ +Processing module test48 (test_input/test48.py)... + +Warnings... + +test_input/test48.py:10: Object (i) has no attribute (has_no_method) +test_input/test48.py:11: Object (l) has no attribute (has_no_method) +test_input/test48.py:12: Object (d) has no attribute (has_no_method) +test_input/test48.py:13: Object (s) has no attribute (has_no_method) +test_input/test48.py:14: Object (n) has no attribute (has_no_method) +test_input/test48.py:15: Object (e) has no attribute (has_no_method) +test_input/test48.py:17: Object (i) has no attribute (has_no_attr) +test_input/test48.py:18: Object (l) has no attribute (has_no_attr) +test_input/test48.py:19: Object (d) has no attribute (has_no_attr) +test_input/test48.py:20: Object (s) has no attribute (has_no_attr) +test_input/test48.py:21: Object (n) has no attribute (has_no_attr) +test_input/test48.py:22: Object (e) has no attribute (has_no_attr) +test_input/test48.py:28: Object (jj) has no attribute (a) +test_input/test48.py:29: Object (jj) has no attribute (b) +test_input/test48.py:46: Object (tt) has no attribute (a) +test_input/test48.py:47: Object (tt) has no attribute (b) +test_input/test48.py:53: Statement appears to have no effect +test_input/test48.py:54: Statement appears to have no effect +test_input/test48.py:55: Statement appears to have no effect +test_input/test48.py:56: Statement appears to have no effect +test_input/test48.py:57: Statement appears to have no effect +test_input/test48.py:58: Statement appears to have no effect +test_input/test48.py:59: Statement appears to have no effect +test_input/test48.py:63: Statement appears to have no effect +test_input/test48.py:65: Statement appears to have no effect +test_input/test48.py:66: Statement appears to have no effect +test_input/test48.py:70: Statement appears to have no effect +test_input/test48.py:71: Statement appears to have no effect +test_input/test48.py:72: Statement appears to have no effect +test_input/test48.py:73: Statement appears to have no effect +test_input/test48.py:74: Statement appears to have no effect +test_input/test48.py:75: Statement appears to have no effect +test_input/test48.py:76: Statement appears to have no effect +test_input/test48.py:77: Statement appears to have no effect +test_input/test48.py:78: Statement appears to have no effect +test_input/test48.py:79: Statement appears to have no effect --- /dev/null +++ pychecker-0.8.19/test_expected/test93 @@ -0,0 +1,6 @@ +Processing module test93 (test_input/test93.py)... + +Warnings... + +test_input/test93.py:6: Passing a constant string to getattr, consider direct reference +test_input/test93.py:11: Passing a constant string to setattr, consider direct reference --- /dev/null +++ pychecker-0.8.19/test_expected/test88-2.5 @@ -0,0 +1,11 @@ +Processing module test88 (test_input/test88.py)... +test_input/test88.py:10: DeprecationWarning: the gopherlib module is deprecated + import gopherlib + +Warnings... + +test_input/test88.py:10: gopherlib module is deprecated +test_input/test88.py:17: whrandom module is deprecated, consider using random +test_input/test88.py:26: os.tempnam() is a security problem +test_input/test88.py:27: os.tmpnam() is a security problem +test_input/test88.py:29: string.atof is deprecated --- /dev/null +++ pychecker-0.8.19/test_expected/test22-2.5 @@ -0,0 +1,31 @@ +Processing module test22 (test_input/test22.py)... + +Warnings... + +test_input/test22.py:6: Format string argument count (4) doesn't match arguments (3) +test_input/test22.py:9: Local variable (eee) not used +test_input/test22.py:10: No local variable (ccc) +test_input/test22.py:10: No local variable (ddd) +test_input/test22.py:13: No local variable () +test_input/test22.py:15: Invalid format string, problem starts near: '(b) ' +test_input/test22.py:16: Invalid format string, problem starts near: '(b)' +test_input/test22.py:19: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:22: Format string argument count (3) doesn't match arguments (4) +test_input/test22.py:24: Invalid format string, problem starts near: 'z ' +test_input/test22.py:25: Invalid format string, problem starts near: 'J ' +test_input/test22.py:26: Too many *s in format flags +test_input/test22.py:28: Can't mix tuple/mapping (dictionary) formats in same format string +test_input/test22.py:29: Can't use * in formats when using a mapping (dictionary), near: '*d' +test_input/test22.py:31: Can't use * in formats when using a mapping (dictionary), near: '*.*f' +test_input/test22.py:34: Format string argument count (3) doesn't match arguments (2) +test_input/test22.py:40: Format string argument count (2) doesn't match arguments (1) +test_input/test22.py:42: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:46: Format string argument count (1) doesn't match arguments (3) +test_input/test22.py:51: Format string argument count (1) doesn't match arguments (2) +test_input/test22.py:65: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:66: Format string argument count (3) doesn't match arguments (4) +test_input/test22.py:67: Format string argument count (4) doesn't match arguments (2) +test_input/test22.py:70: Local variable (c) not used +test_input/test22.py:74: Local variable (a) not used +test_input/test22.py:74: Local variable (b) not used +test_input/test22.py:86: Invalid format string, problem starts near: '' (end of format string) --- /dev/null +++ pychecker-0.8.19/test_expected/test55 @@ -0,0 +1,9 @@ +Processing module test55 (test_input/test55.py)... + +Warnings... + +test_input/test55.py:6: (RuntimeError) shadows builtin +test_input/test55.py:6: Local variable (RuntimeError) not used +test_input/test55.py:6: Setting exception to builtin (RuntimeError), consider () around exceptions +test_input/test55.py:29: (RuntimeError) shadows builtin +test_input/test55.py:29: Setting exception to builtin (RuntimeError), consider () around exceptions --- /dev/null +++ pychecker-0.8.19/test_expected/test6 @@ -0,0 +1,5 @@ +Processing module test6 (test_input/test6.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test73 @@ -0,0 +1,9 @@ +Processing module test73 (test_input/test73.py)... + +Warnings... + +test_input/test73.py:12: Methods (f, g) in Abstract need to be overridden in a subclass +test_input/test73.py:13: Methods (f) in ConcreteBad need to be overridden in a subclass +test_input/test73.py:22: Methods (f) in AbstractInst need to be overridden in a subclass +test_input/test73.py:36: Methods (abstract) in import73.AbstractLib need to be overridden in a subclass +test_input/test73.py:37: Methods (abstract) in ImplAbstract need to be overridden in a subclass --- /dev/null +++ pychecker-0.8.19/test_expected/test68-2.6 @@ -0,0 +1,5 @@ +Processing module test68 (test_input/test68.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test80-2.2 @@ -0,0 +1,6 @@ +Processing module test80 (test_input/test80.py)... + +Warnings... + +test_input/test80.py:8: Variable (x) already has types ['int'] and set to float +test_input/test80.py:23: Variable (y) already has types ['list'] and set to dict --- /dev/null +++ pychecker-0.8.19/test_expected/test43 @@ -0,0 +1,5 @@ +Processing module test43 (test_input/test43.py)... + +Warnings... + +test_input/test43.py:11: No class attribute (isIntersecting) found --- /dev/null +++ pychecker-0.8.19/test_expected/test11 @@ -0,0 +1,5 @@ +Processing module test11 (test_input/test11.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test39 @@ -0,0 +1,14 @@ +Processing module test39 (test_input/test39.py)... + +Warnings... + +test_input/test39.py:3: No doc string for function func2 +test_input/test39.py:10: s is not first method argument +test_input/test39.py:11: No doc string for class X2 +test_input/test39.py:14: No doc string for function a +test_input/test39.py:19: No doc string for function a +test_input/test39.py:29: No doc string for function x +test_input/test39.py:31: No doc string for function y +test_input/test39.py:33: No doc string for function z +test_input/test39.py:33: Parameter (jjj) not used +test_input/test39.py:34: Local variable (j) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test102 @@ -0,0 +1,5 @@ +Processing module test102 (test_input/test102.py)... + +Warnings... + +test_input/test102.py:8: __getattr__ should not return None, raise an exception if not found --- /dev/null +++ pychecker-0.8.19/test_expected/test99 @@ -0,0 +1,5 @@ +Processing module test99 (test_input/test99.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test80 @@ -0,0 +1,6 @@ +Processing module test80 (test_input/test80.py)... + +Warnings... + +test_input/test80.py:8: Variable (x) already has types ['int'] and set to float +test_input/test80.py:23: Variable (y) already has types ['list'] and set to dictionary --- /dev/null +++ pychecker-0.8.19/test_expected/test28 @@ -0,0 +1,5 @@ +Processing module test28 (test_input/test28.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test47 @@ -0,0 +1,5 @@ +Processing module test47 (test_input/test47.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test62 @@ -0,0 +1,5 @@ +Processing module test62 (test_input/test62.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test42 @@ -0,0 +1,5 @@ +Processing module test42 (test_input/test42.py)... + +Warnings... + +test_input/test42.py:11: sys.exc_traceback is deprecated --- /dev/null +++ pychecker-0.8.19/test_expected/test5 @@ -0,0 +1,5 @@ +Processing module test5 (test_input/test5.py)... + +Warnings... + +test_input/test5.py:8: Function (x) uses named arguments --- /dev/null +++ pychecker-0.8.19/test_expected/test40 @@ -0,0 +1,15 @@ +Processing module test40 (test_input/test40.py)... + +Warnings... + +test_input/test40.py:8: Parameter (args) not used +test_input/test40.py:8: Parameter (kw) not used +test_input/test40.py:11: Parameter (kw) not used +test_input/test40.py:17: Parameter (a) not used +test_input/test40.py:17: Parameter (args) not used +test_input/test40.py:17: Parameter (b) not used +test_input/test40.py:17: Parameter (c) not used +test_input/test40.py:17: Parameter (kw) not used +test_input/test40.py:33: Parameter (a) not used +test_input/test40.py:33: Parameter (args) not used +test_input/test40.py:33: Parameter (kw) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test92 @@ -0,0 +1,5 @@ +Processing module test92 (test_input/test92.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test35 @@ -0,0 +1,6 @@ +Processing module test35 (test_input/test35.py)... + +Warnings... + +test_input/test35.py:9: No doc string for function x +test_input/test35.py:11: No doc string for function y --- /dev/null +++ pychecker-0.8.19/test_expected/test10 @@ -0,0 +1,5 @@ +Processing module test10 (test_input/test10.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test27-2.2 @@ -0,0 +1,5 @@ +Processing module test27 (test_input/test27.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test75-2.2 @@ -0,0 +1,9 @@ +Processing module test75 (test_input/test75.py)... + +Warnings... + +test_input/test75.py:5: Using __slots__ in classic class A has no effect, consider deriving from object +test_input/test75.py:14: __slots__ are empty in C +test_input/test75.py:26: Using property (x) in classic class E may not work +test_input/test75.py:45: ['cls', 'klass'] is not first classmethod argument +test_input/test75.py:49: self is argument in staticmethod --- /dev/null +++ pychecker-0.8.19/test_expected/test46 @@ -0,0 +1,10 @@ +Processing module test46 (test_input/test46.py)... + +Warnings... + +test_input/test46.py:5: Imported module (test46) not used +test_input/test46.py:5: Module (test46) imports itself +test_input/test46.py:6: Module (test46) imports itself +test_input/test46.py:6: Using import and from ... import for (test46) +test_input/test46.py:7: Module (test46) imports itself +test_input/test46.py:7: Using import and from ... import for (test46) --- /dev/null +++ pychecker-0.8.19/test_expected/test67 @@ -0,0 +1,5 @@ +Processing module test67 (test_input/test67.py)... + +Warnings... + +test_input/test67.py:8: Members (a, d) not used in class (X) --- /dev/null +++ pychecker-0.8.19/test_expected/test3-2.4 @@ -0,0 +1,8 @@ +Processing module test3 (test_input/test3.py)... + +Warnings... + +[system path]/UserDict.py:4: No doc string for class UserDict + +test_input/test3.py:7: No global (x) found +test_input/test3.py:12: No doc string for class jj --- /dev/null +++ pychecker-0.8.19/test_expected/test20-2.6 @@ -0,0 +1,6 @@ +Processing module test20 (test_input/test20.py)... + +Warnings... + +test_input/test20.py:21: Function return types are inconsistent +test_input/test20.py:40: Function return types are inconsistent --- /dev/null +++ pychecker-0.8.19/test_expected/test58-2.2 @@ -0,0 +1,14 @@ +Processing module test58 (test_input/test58.py)... +:3: Warning: 'yield' will become a reserved keyword in the future +:6: Warning: 'yield' will become a reserved keyword in the future +:7: Warning: 'yield' will become a reserved keyword in the future +:10: Warning: 'yield' will become a reserved keyword in the future + +Warnings... + +test_input/test58.py:3: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:6: Local variable (yield) shadows global defined on line 3 +test_input/test58.py:6: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:7: Local variable (yield) shadows global defined on line 3 +test_input/test58.py:7: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:10: Using identifier (yield) which will become a keyword in version 2.2 --- /dev/null +++ pychecker-0.8.19/test_expected/test66 @@ -0,0 +1,5 @@ +Processing module test66 (test_input/test66.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test4 @@ -0,0 +1,6 @@ +Processing module test4 (test_input/test4.py)... + +Warnings... + +test_input/test4.py:1: No module doc string +test_input/test4.py:11: Base class (UserDict.UserDict) __init__() not called --- /dev/null +++ pychecker-0.8.19/test_expected/test41 @@ -0,0 +1,7 @@ +Processing module test41 (test_input/test41.py)... + +Warnings... + +test_input/test41.py:4: Redefining attribute (x) original line (3) +test_input/test41.py:8: Redefining attribute (X) original line (6) +test_input/test41.py:14: Redefining attribute (x) original line (13) --- /dev/null +++ pychecker-0.8.19/test_expected/test98 @@ -0,0 +1,8 @@ +Processing module test98 (test_input/test98.py)... + +Warnings... + +test_input/import98.py:11: Cannot return a value from __init__ + +test_input/test98.py:15: Cannot return a value from __init__ +test_input/test98.py:29: Cannot return a value from __init__ --- /dev/null +++ pychecker-0.8.19/test_expected/test88-2.6 @@ -0,0 +1,9 @@ +Processing module test88 (test_input/test88.py)... + +Warnings... + +test_input/test88.py:10: gopherlib module is deprecated +test_input/test88.py:17: whrandom module is deprecated, consider using random +test_input/test88.py:26: os.tempnam() is a security problem +test_input/test88.py:27: os.tmpnam() is a security problem +test_input/test88.py:29: string.atof is deprecated --- /dev/null +++ pychecker-0.8.19/test_expected/test25 @@ -0,0 +1,8 @@ +Processing module test25 (test_input/test25.py)... + +Warnings... + +test_input/test25.py:11: Invalid arguments to (x), got 0, expected 1 +test_input/test25.py:13: No class attribute (a) found +test_input/test25.py:14: No class attribute (y) found +test_input/test25.py:15: No module attribute (lkjsdflksjasdlf) found --- /dev/null +++ pychecker-0.8.19/test_expected/test23 @@ -0,0 +1,8 @@ +Processing module test23 (test_input/test23.py)... + +Warnings... + +test_input/test23.py:13: Using method (x) as an attribute (not invoked) +test_input/test23.py:15: Using method (x) as an attribute (not invoked) +test_input/test23.py:17: Using method (x) as an attribute (not invoked) +test_input/test23.py:39: Using method (x) as an attribute (not invoked) --- /dev/null +++ pychecker-0.8.19/test_expected/test34 @@ -0,0 +1,14 @@ +Processing module test34 (test_input/test34.py)... + +Warnings... + +getopt.py:25: No doc string for class GetoptError + +test_input/test34.py:1: No doc string for class Error +test_input/test34.py:6: Module member (string) re-imported with * +test_input/test34.py:9: Using import and from ... import for (locale) +test_input/test34.py:10: Using import and from ... import for (locale) +test_input/test34.py:13: Using import and from ... import for (getopt) +test_input/test34.py:16: Using import and from ... import for (copy) +test_input/test34.py:19: Module member (from re import sub) re-imported +test_input/test34.py:22: Module (ihooks) re-imported --- /dev/null +++ pychecker-0.8.19/test_expected/test1-2.5 @@ -0,0 +1,33 @@ +Processing module test1 (test_input/test1.py)... + +Warnings... + +test_input/test1.py:1: No module doc string +test_input/test1.py:2: Imported module (imp) not used +test_input/test1.py:3: Imported module (re) not used +test_input/test1.py:5: Variable (_NOT_USED1) not used +test_input/test1.py:10: Local variable (m) not used +test_input/test1.py:10: No global (unknownList) found +test_input/test1.py:13: self is argument in function +test_input/test1.py:21: Invalid arguments to (jjj2), got 0, expected between 1 and 3 +test_input/test1.py:25: Invalid arguments to (jjj2), got 4, expected between 1 and 3 +test_input/test1.py:28: Invalid arguments to (ddd), got 0, expected at least 1 +test_input/test1.py:34: No doc string for class X +test_input/test1.py:34: No doc string for class Y +test_input/test1.py:35: No global (sys) found +test_input/test1.py:36: No class attribute (__x__) found +test_input/test1.py:36: No class attribute (x) found +test_input/test1.py:39: self is not first method argument +test_input/test1.py:40: No global (nofunc) found +test_input/test1.py:41: Local variable (i) not used +test_input/test1.py:41: No class attribute (a) found +test_input/test1.py:41: No global (self) found +test_input/test1.py:42: Function (jjj) doesn't support **kwArgs +test_input/test1.py:42: Invalid arguments to (jjj), got 3, expected 1 +test_input/test1.py:46: Local variable (asdf) not used +test_input/test1.py:48: Local variable (j) not used +test_input/test1.py:48: No global (jjjj) found +test_input/test1.py:50: No class attribute (z) found +test_input/test1.py:54: Invalid arguments to (xxx), got 2, expected 1 +test_input/test1.py:70: (str) shadows builtin +test_input/test1.py:75: Function (append) doesn't support **kwArgs --- /dev/null +++ pychecker-0.8.19/test_expected/test78 @@ -0,0 +1,5 @@ +Processing module test78 (test_input/test78.py)... + +Warnings... + +test_input/test78.py:6: Using input() is a security problem, consider using raw_input() --- /dev/null +++ pychecker-0.8.19/test_expected/test52 @@ -0,0 +1,5 @@ +Processing module test52 (test_input/test52.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test37 @@ -0,0 +1,5 @@ +Processing module test37 (test_input/test37.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test34-2.2 @@ -0,0 +1,17 @@ +Processing module test34 (test_input/test34.py)... + +Warnings... + +[system path]/locale.py:168: (str) shadows builtin +[system path]/locale.py:173: (str) shadows builtin + +/usr/src/build/228093-i386/install/usr/lib/python2.2/getopt.py:25: No doc string for class GetoptError + +test_input/test34.py:1: No doc string for class Error +test_input/test34.py:6: Module member (string) re-imported with * +test_input/test34.py:9: Using import and from ... import for (locale) +test_input/test34.py:10: Using import and from ... import for (locale) +test_input/test34.py:13: Using import and from ... import for (getopt) +test_input/test34.py:16: Using import and from ... import for (copy) +test_input/test34.py:19: Module member (from re import sub) re-imported +test_input/test34.py:22: Module (ihooks) re-imported --- /dev/null +++ pychecker-0.8.19/test_expected/test72 @@ -0,0 +1,8 @@ +Processing module test72 (test_input/test72.py)... + +Warnings... + +test_input/test72.py:8: Setting class attribute (y) not set in __init__ +test_input/test72.py:13: Setting class attribute (z) not set in __init__ +test_input/test72.py:23: No class attribute (z) found +test_input/test72.py:24: Setting class attribute (y) not set in __init__ --- /dev/null +++ pychecker-0.8.19/test_expected/test9 @@ -0,0 +1,6 @@ +Processing module test9 (test_input/test9.py)... + +Warnings... + +test_input/test9.py:8: Module (getopt) re-imported +test_input/test9.py:15: No module attribute (xyz) found --- /dev/null +++ pychecker-0.8.19/test_expected/test103-2.4 @@ -0,0 +1,5 @@ +Processing module test103 (test_input/test103.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test21 @@ -0,0 +1,7 @@ +Processing module test21 (test_input/test21.py)... + +Warnings... + +test_input/test21.py:9: Function return types are inconsistent +test_input/test21.py:15: Function return types are inconsistent +test_input/test21.py:21: Function return types are inconsistent --- /dev/null +++ pychecker-0.8.19/test_expected/test20 @@ -0,0 +1,7 @@ +Processing module test20 (test_input/test20.py)... + +Warnings... + +test_input/test20.py:11: Function returns a value and also implicitly returns None +test_input/test20.py:21: Function return types are inconsistent +test_input/test20.py:40: Function return types are inconsistent --- /dev/null +++ pychecker-0.8.19/test_expected/test89 @@ -0,0 +1,11 @@ +Processing module test89 (test_input/test89.py)... + Caught exception importing module test89: + File "./pychecker/checker.py", line 536, in setupMainCode() + module = imp.load_module(self.moduleName, file, filename, smt) + File "test_input/test89.py", line 3 + class Newbie(object): + NameError: name 'object' is not defined + +Warnings... + +test_input/test89.py:1: NOT PROCESSED UNABLE TO IMPORT --- /dev/null +++ pychecker-0.8.19/test_expected/test101 @@ -0,0 +1,5 @@ +Processing module test101 (test_input/test101.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test29 @@ -0,0 +1,5 @@ +Processing module test29 (test_input/test29.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test49 @@ -0,0 +1,8 @@ +Processing module test49 (test_input/test49.py)... + +Warnings... + +test_input/test49.py:5: Using integer division (d / e) may return integer or float +test_input/test49.py:6: Using integer division (d / 3) may return integer or float +test_input/test49.py:7: Using integer division (7 / e) may return integer or float +test_input/test49.py:8: Using integer division (5 / 6) may return integer or float --- /dev/null +++ pychecker-0.8.19/test_expected/test33 @@ -0,0 +1,5 @@ +Processing module test33 (test_input/test33.py)... + +Warnings... + +test_input/test33.py:4: Variable (j) used before being set --- /dev/null +++ pychecker-0.8.19/test_expected/test95 @@ -0,0 +1,5 @@ +Processing module test95 (test_input/test95.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test58 @@ -0,0 +1,10 @@ +Processing module test58 (test_input/test58.py)... + +Warnings... + +test_input/test58.py:3: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:6: Local variable (yield) shadows global defined on line 3 +test_input/test58.py:6: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:7: Local variable (yield) shadows global defined on line 3 +test_input/test58.py:7: Using identifier (yield) which will become a keyword in version 2.2 +test_input/test58.py:10: Using identifier (yield) which will become a keyword in version 2.2 --- /dev/null +++ pychecker-0.8.19/test_expected/test1 @@ -0,0 +1,35 @@ +Processing module test1 (test_input/test1.py)... +test_input/test1.py:67: SyntaxWarning: local name 'b' in 'test_kw_lambda' shadows use of 'b' as global in nested scope 'lambda' + def test_kw_lambda(a, b, c): + +Warnings... + +test_input/test1.py:1: No module doc string +test_input/test1.py:2: Imported module (imp) not used +test_input/test1.py:3: Imported module (re) not used +test_input/test1.py:5: Variable (_NOT_USED1) not used +test_input/test1.py:10: Local variable (m) not used +test_input/test1.py:10: No global (unknownList) found +test_input/test1.py:13: self is argument in function +test_input/test1.py:21: Invalid arguments to (jjj2), got 0, expected between 1 and 3 +test_input/test1.py:25: Invalid arguments to (jjj2), got 4, expected between 1 and 3 +test_input/test1.py:28: Invalid arguments to (ddd), got 0, expected at least 1 +test_input/test1.py:34: No doc string for class X +test_input/test1.py:34: No doc string for class Y +test_input/test1.py:35: No global (sys) found +test_input/test1.py:36: No class attribute (__x__) found +test_input/test1.py:36: No class attribute (x) found +test_input/test1.py:39: self is not first method argument +test_input/test1.py:40: No global (nofunc) found +test_input/test1.py:41: Local variable (i) not used +test_input/test1.py:41: No class attribute (a) found +test_input/test1.py:41: No global (self) found +test_input/test1.py:42: Function (jjj) doesn't support **kwArgs +test_input/test1.py:42: Invalid arguments to (jjj), got 3, expected 1 +test_input/test1.py:46: Local variable (asdf) not used +test_input/test1.py:48: Local variable (j) not used +test_input/test1.py:48: No global (jjjj) found +test_input/test1.py:50: No class attribute (z) found +test_input/test1.py:54: Invalid arguments to (xxx), got 2, expected 1 +test_input/test1.py:70: (str) shadows builtin +test_input/test1.py:75: Function (append) doesn't support **kwArgs --- /dev/null +++ pychecker-0.8.19/test_expected/test64 @@ -0,0 +1,9 @@ +Processing module test64 (test_input/test64.py)... + +Warnings... + +test_input/test64.py:1: No doc string for class _Anything +test_input/test64.py:4: Imported module (re) not used +test_input/test64.py:4: Imported module (sys) not used +test_input/test64.py:5: Imported module (array) not used +test_input/test64.py:14: Local variable (y) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test74 @@ -0,0 +1,11 @@ +Processing module test74 (test_input/test74.py)... + +Warnings... + +test_input/test74.py:10: Using __getattribute__ in old-style class (B) does not work +test_input/test74.py:17: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:20: Using __getattribute__ in old-style class (D) does not work +test_input/test74.py:22: __getattribute__ should not return None, raise an exception if not found +test_input/test74.py:30: Function returns a value and also implicitly returns None +test_input/test74.py:30: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:41: Passing a constant string to getattr, consider direct reference --- /dev/null +++ pychecker-0.8.19/test_expected/test61 @@ -0,0 +1,12 @@ +Processing module test61 (test_input/test61.py)... + +Warnings... + +test_input/test61.py:9: Invalid arguments to (x), got 0, expected 2 +test_input/test61.py:18: Invalid arguments to (get), got 3, expected between 1 and 2 +test_input/test61.py:20: Invalid arguments to (keys), got 3, expected 0 +test_input/test61.py:21: Using the return value from (d.clear) which is always None +test_input/test61.py:22: Using the return value from (d.clear) which is always None +test_input/test61.py:23: Using the return value from (d.clear) which is always None +test_input/test61.py:26: Passing a constant string to setattr, consider direct reference +test_input/test61.py:26: Using the return value from (setattr) which is always None --- /dev/null +++ pychecker-0.8.19/test_expected/test100 @@ -0,0 +1,5 @@ +Processing module test100 (test_input/test100.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test83 @@ -0,0 +1,9 @@ +Processing module test83 (test_input/test83.py)... + +Warnings... + +test_input/test83.py:9: Unpacking 2 values into 3 variables +test_input/test83.py:14: Unpacking 2 values into 3 variables +test_input/test83.py:18: Unpacking 2 values into 1 variables +test_input/test83.py:22: Unpacking 1 values into 2 variables +test_input/test83.py:26: Unpacking a non-sequence (5) of type int --- /dev/null +++ pychecker-0.8.19/test_expected/test54 @@ -0,0 +1,9 @@ +Processing module test54 (test_input/test54.py)... + +Warnings... + +test_input/test54.py:7: Variable (z) deleted before being set +test_input/test54.py:9: Local variable (a) has already been deleted on line 6 +test_input/test54.py:12: (a) cannot be used after being deleted on line 9 +test_input/test54.py:15: No global (no_global) found +test_input/test54.py:18: No global (another_non_existant_global) found --- /dev/null +++ pychecker-0.8.19/test_expected/test36 @@ -0,0 +1,7 @@ +Processing module test36 (test_input/test36.py)... + +Warnings... + +test_input/test36.py:1: No doc string for class NoneType +test_input/test36.py:31: Function (int) doesn't support **kwArgs for name (args) +test_input/test36.py:36: [].append() only takes 1 argument in Python 1.6 and above for (n) --- /dev/null +++ pychecker-0.8.19/test_expected/test69 @@ -0,0 +1,5 @@ +Processing module test69 (test_input/test69.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test17 @@ -0,0 +1,8 @@ +Processing module test17 (test_input/test17.py)... + +Warnings... + +test_input/test17.py:7: Cannot return a value from __init__ +test_input/test17.py:13: Cannot return a value from __init__ +test_input/test17.py:15: Cannot return a value from __init__ +test_input/test17.py:16: Cannot return a value from __init__ --- /dev/null +++ pychecker-0.8.19/test_expected/test51 @@ -0,0 +1,6 @@ +Processing module test51 (test_input/test51.py)... + +Warnings... + +test_input/test51.py:7: Using a tuple instead of slice as list accessor for (n) +test_input/test51.py:8: Using a tuple instead of slice as list accessor for (n) --- /dev/null +++ pychecker-0.8.19/test_expected/test30 @@ -0,0 +1,5 @@ +Processing module test30 (test_input/test30.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test58-2.3 @@ -0,0 +1,8 @@ +Processing module test58 (test_input/test58.py)... + SyntaxError: invalid syntax (test_input/test58.py, line 3) + yield = None + ^ + +Warnings... + +test_input/test58.py:1: NOT PROCESSED UNABLE TO IMPORT --- /dev/null +++ pychecker-0.8.19/test_expected/test19 @@ -0,0 +1,6 @@ +Processing module test19 (test_input/test19.py)... + +Warnings... + +test_input/test19.py:8: Invalid arguments to (__init__), got 2, expected between 0 and 1 +test_input/test19.py:9: Invalid arguments to (__init__), got 3, expected between 0 and 1 --- /dev/null +++ pychecker-0.8.19/test_expected/test3-2.2 @@ -0,0 +1,8 @@ +Processing module test3 (test_input/test3.py)... + +Warnings... + +/usr/src/build/228093-i386/install/usr/lib/python2.2/UserDict.py:4: No doc string for class UserDict + +test_input/test3.py:7: No global (x) found +test_input/test3.py:12: No doc string for class jj --- /dev/null +++ pychecker-0.8.19/test_expected/test63 @@ -0,0 +1,5 @@ +Processing module test63 (test_input/test63.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test26 @@ -0,0 +1,5 @@ +Processing module test26 (test_input/test26.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test34-2.4 @@ -0,0 +1,14 @@ +Processing module test34 (test_input/test34.py)... + +Warnings... + +[system path]/getopt.py:42: No doc string for class GetoptError + +test_input/test34.py:1: No doc string for class Error +test_input/test34.py:6: Module member (string) re-imported with * +test_input/test34.py:9: Using import and from ... import for (locale) +test_input/test34.py:10: Using import and from ... import for (locale) +test_input/test34.py:13: Using import and from ... import for (getopt) +test_input/test34.py:16: Using import and from ... import for (copy) +test_input/test34.py:19: Module member (from re import sub) re-imported +test_input/test34.py:22: Module (ihooks) re-imported --- /dev/null +++ pychecker-0.8.19/test_expected/test56 @@ -0,0 +1,5 @@ +Processing module test56 (test_input/test56.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test87-2.5 @@ -0,0 +1,25 @@ +Processing module test87 (test_input/test87.py)... + +Warnings... + +test_input/test87.py:3: (True) shadows builtin +test_input/test87.py:3: Should not assign to True, it is (or will be) a builtin +test_input/test87.py:4: (False) shadows builtin +test_input/test87.py:4: Should not assign to False, it is (or will be) a builtin +test_input/test87.py:6: Should not assign to true, it is similar to builtin True +test_input/test87.py:7: Should not assign to false, it is similar to builtin False +test_input/test87.py:9: Should not assign to TRUE, it is similar to builtin True +test_input/test87.py:10: Should not assign to FALSE, it is similar to builtin False +test_input/test87.py:14: Comparisons with TRUE are not necessary and may not work as expected +test_input/test87.py:16: Comparisons with TRUE are not necessary and may not work as expected +test_input/test87.py:17: Comparisons with True are not necessary and may not work as expected +test_input/test87.py:18: Comparisons with true are not necessary and may not work as expected +test_input/test87.py:20: Comparisons with false are not necessary and may not work as expected +test_input/test87.py:22: Using is false, may not always work +test_input/test87.py:24: Using is True, may not always work +test_input/test87.py:26: Using is 53343, may not always work +test_input/test87.py:28: Using is 10000000.0, may not always work +test_input/test87.py:30: Using is not false, may not always work +test_input/test87.py:32: Using is not True, may not always work +test_input/test87.py:34: Using is not 53343, may not always work +test_input/test87.py:36: Using is not 10000000.0, may not always work --- /dev/null +++ pychecker-0.8.19/test_expected/test22 @@ -0,0 +1,33 @@ +Processing module test22 (test_input/test22.py)... + +Warnings... + +test_input/test22.py:6: Format string argument count (4) doesn't match arguments (3) +test_input/test22.py:9: Local variable (eee) not used +test_input/test22.py:10: No local variable (ccc) +test_input/test22.py:10: No local variable (ddd) +test_input/test22.py:13: No local variable () +test_input/test22.py:15: Invalid format string, problem starts near: '(b) ' +test_input/test22.py:16: Invalid format string, problem starts near: '(b)' +test_input/test22.py:19: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:22: Format string argument count (3) doesn't match arguments (4) +test_input/test22.py:24: Invalid format string, problem starts near: 'z ' +test_input/test22.py:25: Invalid format string, problem starts near: 'J ' +test_input/test22.py:26: Too many *s in format flags +test_input/test22.py:28: Can't mix tuple/mapping (dictionary) formats in same format string +test_input/test22.py:29: Can't use * in formats when using a mapping (dictionary), near: '*d' +test_input/test22.py:31: Can't use * in formats when using a mapping (dictionary), near: '*.*f' +test_input/test22.py:34: Format string argument count (3) doesn't match arguments (2) +test_input/test22.py:40: Format string argument count (2) doesn't match arguments (1) +test_input/test22.py:42: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:46: Format string argument count (1) doesn't match arguments (3) +test_input/test22.py:51: Format string argument count (1) doesn't match arguments (2) +test_input/test22.py:65: Format string argument count (2) doesn't match arguments (3) +test_input/test22.py:66: Format string argument count (3) doesn't match arguments (4) +test_input/test22.py:67: Format string argument count (4) doesn't match arguments (2) +test_input/test22.py:70: Local variable (c) not used +test_input/test22.py:74: Local variable (a) not used +test_input/test22.py:74: Local variable (b) not used +test_input/test22.py:79: ... % 1 may be constant +test_input/test22.py:81: ... % 1 may be constant +test_input/test22.py:86: Invalid format string, problem starts near: '' (end of format string) --- /dev/null +++ pychecker-0.8.19/test_expected/test45 @@ -0,0 +1,6 @@ +Processing module test45 (test_input/test45.py)... + +Warnings... + +test_input/test45.py:17: Parameter (other) not used +test_input/test45.py:19: Parameter (other1) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test71-2.4 @@ -0,0 +1,8 @@ +Processing module test71 (test_input/test71.py)... + +Warnings... + +test_input/test71.py:8: Code appears to be unreachable +test_input/test71.py:14: Code appears to be unreachable +test_input/test71.py:20: Code appears to be unreachable +test_input/test71.py:26: Code appears to be unreachable --- /dev/null +++ pychecker-0.8.19/test_expected/test12 @@ -0,0 +1,5 @@ +Processing module test12 (test_input/test12.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test20-2.4 @@ -0,0 +1,6 @@ +Processing module test20 (test_input/test20.py)... + +Warnings... + +test_input/test20.py:21: Function return types are inconsistent +test_input/test20.py:40: Function return types are inconsistent --- /dev/null +++ pychecker-0.8.19/test_expected/test87 @@ -0,0 +1,25 @@ +Processing module test87 (test_input/test87.py)... + +Warnings... + +test_input/test87.py:3: (True) shadows builtin +test_input/test87.py:3: Should not assign to True, it is (or will be) a builtin +test_input/test87.py:4: (False) shadows builtin +test_input/test87.py:4: Should not assign to False, it is (or will be) a builtin +test_input/test87.py:6: Should not assign to true, it is similar to builtin True +test_input/test87.py:7: Should not assign to false, it is similar to builtin False +test_input/test87.py:9: Should not assign to TRUE, it is similar to builtin True +test_input/test87.py:10: Should not assign to FALSE, it is similar to builtin False +test_input/test87.py:14: Comparisons with TRUE are not necessary and may not work as expected +test_input/test87.py:16: Comparisons with TRUE are not necessary and may not work as expected +test_input/test87.py:16: Comparisons with True are not necessary and may not work as expected +test_input/test87.py:16: Comparisons with true are not necessary and may not work as expected +test_input/test87.py:20: Comparisons with false are not necessary and may not work as expected +test_input/test87.py:22: Using is false, may not always work +test_input/test87.py:24: Using is True, may not always work +test_input/test87.py:26: Using is 53343, may not always work +test_input/test87.py:28: Using is 10000000.0, may not always work +test_input/test87.py:30: Using is not false, may not always work +test_input/test87.py:32: Using is not True, may not always work +test_input/test87.py:34: Using is not 53343, may not always work +test_input/test87.py:36: Using is not 10000000.0, may not always work --- /dev/null +++ pychecker-0.8.19/test_expected/test3-2.3 @@ -0,0 +1,9 @@ +Processing module test3 (test_input/test3.py)... + +Warnings... + +[system path]/UserDict.py:4: No doc string for class UserDict +[system path]/UserDict.py:8: (dict) shadows builtin + +test_input/test3.py:7: No global (x) found +test_input/test3.py:12: No doc string for class jj --- /dev/null +++ pychecker-0.8.19/test_expected/test88 @@ -0,0 +1,9 @@ +Processing module test88 (test_input/test88.py)... + +Warnings... + +test_input/test88.py:10: gopherlib module is deprecated +test_input/test88.py:17: whrandom module is deprecated, consider using random +test_input/test88.py:26: os.tempnam() is a security problem +test_input/test88.py:27: os.tmpnam() is a security problem +test_input/test88.py:29: string.atof is deprecated --- /dev/null +++ pychecker-0.8.19/test_expected/test18 @@ -0,0 +1,16 @@ +Processing module test18 (test_input/test18.py)... + +Warnings... + +test_input/test18.py:21: Invalid arguments to (__init__), got 1, expected 0 +test_input/test18.py:23: Invalid arguments to (__init__), got 0, expected 1 +test_input/test18.py:25: Invalid arguments to (__init__), got 2, expected 1 +test_input/test18.py:26: Invalid arguments to (__init__), got 3, expected 1 +test_input/test18.py:27: Invalid arguments to (__init__), got 4, expected 1 +test_input/test18.py:29: Invalid arguments to (__init__), got 0, expected 3 +test_input/test18.py:30: Invalid arguments to (__init__), got 1, expected 3 +test_input/test18.py:31: Invalid arguments to (__init__), got 2, expected 3 +test_input/test18.py:33: Invalid arguments to (__init__), got 4, expected 3 +test_input/test18.py:35: Invalid arguments to (__init__), got 0, expected at least 3 +test_input/test18.py:36: Invalid arguments to (__init__), got 1, expected at least 3 +test_input/test18.py:37: Invalid arguments to (__init__), got 2, expected at least 3 --- /dev/null +++ pychecker-0.8.19/test_expected/test57 @@ -0,0 +1,5 @@ +Processing module test57 (test_input/test57.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test53-2.5 @@ -0,0 +1,8 @@ +Processing module test53 (test_input/test53.py)... + +Warnings... + +test_input/test53.py:7: Operator (--) doesn't exist, statement has no effect +test_input/test53.py:9: Operator (++) doesn't exist, statement has no effect +test_input/test53.py:22: Format string argument count (2) doesn't match arguments (3) +test_input/test53.py:26: Unary positive (+) usually has no effect --- /dev/null +++ pychecker-0.8.19/test_expected/test8 @@ -0,0 +1,8 @@ +Processing module test8 (test_input/test8.py)... + SyntaxError: invalid syntax (test_input/test8.py, line 4) + syntax error here + ^ + +Warnings... + +test_input/test8.py:1: NOT PROCESSED UNABLE TO IMPORT --- /dev/null +++ pychecker-0.8.19/test_expected/test97 @@ -0,0 +1,5 @@ +Processing module test97 (test_input/test97.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test82 @@ -0,0 +1,5 @@ +Processing module test82 (test_input/test82.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test85 @@ -0,0 +1,6 @@ +Processing module test85 (test_input/test85.py)... + +Warnings... + +test_input/test85.py:13: Using a conditional statement with a constant value (None) +test_input/test85.py:17: Using a conditional statement with a constant value ([]) --- /dev/null +++ pychecker-0.8.19/test_expected/test53 @@ -0,0 +1,9 @@ +Processing module test53 (test_input/test53.py)... + +Warnings... + +test_input/test53.py:5: Operator (~~) doesn't exist, statement has no effect +test_input/test53.py:7: Operator (--) doesn't exist, statement has no effect +test_input/test53.py:9: Operator (++) doesn't exist, statement has no effect +test_input/test53.py:22: Format string argument count (2) doesn't match arguments (3) +test_input/test53.py:26: Unary positive (+) usually has no effect --- /dev/null +++ pychecker-0.8.19/test_expected/test77 @@ -0,0 +1,11 @@ +Processing module test77 (test_input/test77.py)... + Caught exception importing module test77: + File "./pychecker/checker.py", line 698, in setupMainCode() + module = imp.load_module(self.moduleName, file, filename, smt) + File "test_input/test77.py", line 8 + raise MyError("FOO!") + MyError: **error formatting exception value** + +Warnings... + +test_input/test77.py:1: NOT PROCESSED UNABLE TO IMPORT --- /dev/null +++ pychecker-0.8.19/test_expected/test32 @@ -0,0 +1,6 @@ +Processing module test32 (test_input/test32.py)... + +Warnings... + +test_input/test32.py:10: self is not first method argument +test_input/test32.py:15: Invalid arguments to (__init__), got 0, expected 1 --- /dev/null +++ pychecker-0.8.19/test_expected/test31 @@ -0,0 +1,10 @@ +Processing module test31 (test_input/test31.py)... + +Warnings... + +test_input/test31.py:21: Instantiating an object with arguments, but no constructor +test_input/test31.py:22: Instantiating an object with arguments, but no constructor +test_input/test31.py:23: Instantiating an object with arguments, but no constructor +test_input/test31.py:24: Instantiating an object with arguments, but no constructor +test_input/test31.py:25: Function (__init__) doesn't support **kwArgs +test_input/test31.py:26: Invalid arguments to (__init__), got 2, expected 1 --- /dev/null +++ pychecker-0.8.19/test_expected/test84 @@ -0,0 +1,5 @@ +Processing module test84 (test_input/test84.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test68-2.4 @@ -0,0 +1,5 @@ +Processing module test68 (test_input/test68.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test15 @@ -0,0 +1,8 @@ +Processing module test15 (test_input/test15.py)... + +Warnings... + +test_input/test15.py:19: Law of Demeter violated, more than 5 references for (obj.x.y.z.a.b) +test_input/test15.py:20: Law of Demeter violated, more than 5 references for (obj.x.y.z.a.b.c) +test_input/test15.py:30: Law of Demeter violated, more than 6 references for (self.xx.y.z.a.b) +test_input/test15.py:38: Law of Demeter violated, more than 6 references for (self.xx.y.z.a.b.c) --- /dev/null +++ pychecker-0.8.19/test_expected/test38 @@ -0,0 +1,22 @@ +Processing module test38 (test_input/test38.py)... + +Warnings... + +test_input/test38.py:23: Overridden method (m1) doesn't match signature in class (test38.X) +test_input/test38.py:24: Overridden method (m2) doesn't match signature in class (test38.X) +test_input/test38.py:25: Overridden method (m3) doesn't match signature in class (test38.X) +test_input/test38.py:26: Overridden method (m4) doesn't match signature in class (test38.X) +test_input/test38.py:27: Overridden method (m5) doesn't match signature in class (test38.X) +test_input/test38.py:28: Overridden method (m6) doesn't match signature in class (test38.X) +test_input/test38.py:32: Overridden method (m3) doesn't match signature in class (test38.X) +test_input/test38.py:33: Overridden method (m6) doesn't match signature in class (test38.X) +test_input/test38.py:37: Overridden method (m3) doesn't match signature in class (test38.X) +test_input/test38.py:38: Overridden method (m6) doesn't match signature in class (test38.X) +test_input/test38.py:42: Overridden method (m1) doesn't match signature in class (test38.X) +test_input/test38.py:43: Overridden method (m2) doesn't match signature in class (test38.X) +test_input/test38.py:44: Overridden method (m3) doesn't match signature in class (test38.X) +test_input/test38.py:45: Overridden method (m4) doesn't match signature in class (test38.X) +test_input/test38.py:46: Overridden method (m5) doesn't match signature in class (test38.X) +test_input/test38.py:47: Overridden method (m6) doesn't match signature in class (test38.X) +test_input/test38.py:53: Using the exec statement +test_input/test38.py:54: Using the exec statement in global namespace --- /dev/null +++ pychecker-0.8.19/test_expected/test14 @@ -0,0 +1,9 @@ +Processing module test14 (test_input/test14.py)... + +Warnings... + +test_input/test14.py:4: Module (string) re-imported +test_input/test14.py:7: Variable (_unused) not used +test_input/test14.py:10: Local variable (jj) not used +test_input/test14.py:10: Module (string) re-imported +test_input/test14.py:18: Variable (_noglobal) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test2 @@ -0,0 +1,8 @@ +Processing module test2 (test_input/test2.py)... + +Warnings... + +test_input/test2.py:4: Imported module (time) not used +test_input/test2.py:9: No doc string for class X +test_input/test2.py:16: Base class (test2.X) __init__() not called +test_input/test2.py:16: No doc string for class Y --- /dev/null +++ pychecker-0.8.19/test_expected/test81 @@ -0,0 +1,5 @@ +Processing module test81 (test_input/test81.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test74-2.6 @@ -0,0 +1,10 @@ +Processing module test74 (test_input/test74.py)... + +Warnings... + +test_input/test74.py:10: Using __getattribute__ in old-style class (B) does not work +test_input/test74.py:17: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:20: Using __getattribute__ in old-style class (D) does not work +test_input/test74.py:22: __getattribute__ should not return None, raise an exception if not found +test_input/test74.py:30: __getattr__ should not return None, raise an exception if not found +test_input/test74.py:41: Passing a constant string to getattr, consider direct reference --- /dev/null +++ pychecker-0.8.19/test_expected/test86 @@ -0,0 +1,13 @@ +Processing module test86 (test_input/test86.py)... + +Warnings... + +test_input/test86.py:34: Raising string exceptions are deprecated (strerr) +test_input/test86.py:36: Raising string exceptions are deprecated (h) +test_input/test86.py:38: Raising an exception on a non-Exception object (k) +test_input/test86.py:70: Catching string exceptions are deprecated (strerr) +test_input/test86.py:72: Catching string exceptions are deprecated (strerr1) +test_input/test86.py:72: Catching string exceptions are deprecated (strerr2) +test_input/test86.py:74: Catching string exceptions are deprecated (strerr1) +test_input/test86.py:76: Catching string exceptions are deprecated (h) +test_input/test86.py:78: Catching a non-Exception object (k) --- /dev/null +++ pychecker-0.8.19/test_expected/test60 @@ -0,0 +1,6 @@ +Processing module test60 (test_input/test60.py)... + +Warnings... + +test_input/test60.py:3: self is argument in function +test_input/test60.py:9: Using `self` in __repr__ method --- /dev/null +++ pychecker-0.8.19/test_expected/test75 @@ -0,0 +1,6 @@ +Processing module test75 (test_input/test75.py)... + +Warnings... + +test_input/test75.py:5: Using __slots__ in classic class A has no effect, consider deriving from object +test_input/test75.py:8: No global (object) found --- /dev/null +++ pychecker-0.8.19/test_expected/test70 @@ -0,0 +1,12 @@ +Processing module test70 (test_input/test70.py)... + +Warnings... + +test_input/test70.py:18: Using a conditional statement with a constant value (1) +test_input/test70.py:20: Using a conditional statement with a constant value (1) +test_input/test70.py:27: Using a conditional statement with a constant value (21) +test_input/test70.py:29: Using a conditional statement with a constant value (31) +test_input/test70.py:31: Using a conditional statement with a constant value ((x, test)) +test_input/test70.py:32: Using a conditional statement with a constant value ((5, test)) +test_input/test70.py:33: Using a conditional statement with a constant value (5) +test_input/test70.py:35: Using a conditional statement with a constant value (str) --- /dev/null +++ pychecker-0.8.19/test_expected/test71 @@ -0,0 +1,10 @@ +Processing module test71 (test_input/test71.py)... + +Warnings... + +test_input/test71.py:8: Code appears to be unreachable +test_input/test71.py:10: Function returns a value and also implicitly returns None +test_input/test71.py:14: Code appears to be unreachable +test_input/test71.py:16: Function returns a value and also implicitly returns None +test_input/test71.py:20: Code appears to be unreachable +test_input/test71.py:26: Code appears to be unreachable --- /dev/null +++ pychecker-0.8.19/test_expected/test7 @@ -0,0 +1,5 @@ +Processing module test7 (test_input/test7.py)... + +Warnings... + +test_input/test7.py:18: No class attribute (y) found --- /dev/null +++ pychecker-0.8.19/test_expected/test1-2.3 @@ -0,0 +1,33 @@ +Processing module test1 (test_input/test1.py)... + +Warnings... + +test_input/test1.py:1: No module doc string +test_input/test1.py:2: Imported module (imp) not used +test_input/test1.py:3: Imported module (re) not used +test_input/test1.py:5: Variable (_NOT_USED1) not used +test_input/test1.py:10: Local variable (m) not used +test_input/test1.py:10: No global (unknownList) found +test_input/test1.py:13: self is argument in function +test_input/test1.py:21: Invalid arguments to (jjj2), got 0, expected between 1 and 3 +test_input/test1.py:25: Invalid arguments to (jjj2), got 4, expected between 1 and 3 +test_input/test1.py:28: Invalid arguments to (ddd), got 0, expected at least 1 +test_input/test1.py:34: No doc string for class X +test_input/test1.py:34: No doc string for class Y +test_input/test1.py:35: No global (sys) found +test_input/test1.py:36: No class attribute (__x__) found +test_input/test1.py:36: No class attribute (x) found +test_input/test1.py:39: self is not first method argument +test_input/test1.py:40: No global (nofunc) found +test_input/test1.py:41: Local variable (i) not used +test_input/test1.py:41: No class attribute (a) found +test_input/test1.py:41: No global (self) found +test_input/test1.py:42: Function (jjj) doesn't support **kwArgs +test_input/test1.py:42: Invalid arguments to (jjj), got 3, expected 1 +test_input/test1.py:46: Local variable (asdf) not used +test_input/test1.py:48: Local variable (j) not used +test_input/test1.py:48: No global (jjjj) found +test_input/test1.py:50: No class attribute (z) found +test_input/test1.py:54: Invalid arguments to (xxx), got 2, expected 1 +test_input/test1.py:70: (str) shadows builtin +test_input/test1.py:75: Function (append) doesn't support **kwArgs --- /dev/null +++ pychecker-0.8.19/test_expected/test59 @@ -0,0 +1,9 @@ +Processing module test59 (test_input/test59.py)... + +Warnings... + +test_input/test59.py:4: Modifying parameter (c) with a default value may have unexpected consequences +test_input/test59.py:5: Modifying parameter (d) with a default value may have unexpected consequences +test_input/test59.py:19: Modifying parameter (x) with a default value may have unexpected consequences +test_input/test59.py:22: Modifying parameter (a) with a default value may have unexpected consequences +test_input/test59.py:23: Modifying parameter (b) with a default value may have unexpected consequences --- /dev/null +++ pychecker-0.8.19/test_expected/test44 @@ -0,0 +1,5 @@ +Processing module test44 (test_input/test44.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test24 @@ -0,0 +1,10 @@ +Processing module test24 (test_input/test24.py)... + +Warnings... + +test_input/import24.py:4: No doc string for class Aaa +test_input/import24.py:8: Base class (import24.Aaa) __init__() not called +test_input/import24.py:8: No doc string for class Bbb + +test_input/test24.py:8: Invalid arguments to (func24), got 1, expected 0 +test_input/test24.py:11: Local variable (shadow) shadows global defined on line 0 in file --- /dev/null +++ pychecker-0.8.19/test_expected/test88-2.4 @@ -0,0 +1,11 @@ +Processing module test88 (test_input/test88.py)... +[system path]/whrandom.py:38: DeprecationWarning: the whrandom module is deprecated; please use the random module + DeprecationWarning) + +Warnings... + +test_input/test88.py:10: gopherlib module is deprecated +test_input/test88.py:17: whrandom module is deprecated, consider using random +test_input/test88.py:26: os.tempnam() is a security problem +test_input/test88.py:27: os.tmpnam() is a security problem +test_input/test88.py:29: string.atof is deprecated --- /dev/null +++ pychecker-0.8.19/test_expected/test65 @@ -0,0 +1,5 @@ +Processing module test65 (test_input/test65.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test39-2.2 @@ -0,0 +1,14 @@ +Processing module test39 (test_input/test39.py)... + +Warnings... + +test_input/test39.py:3: No doc string for function func2 +test_input/test39.py:10: No doc string for class X2 +test_input/test39.py:10: s is not first method argument +test_input/test39.py:14: No doc string for function a +test_input/test39.py:19: No doc string for function a +test_input/test39.py:29: No doc string for function x +test_input/test39.py:31: No doc string for function y +test_input/test39.py:33: No doc string for function z +test_input/test39.py:33: Parameter (jjj) not used +test_input/test39.py:34: Local variable (j) not used --- /dev/null +++ pychecker-0.8.19/test_expected/test103-2.2 @@ -0,0 +1,8 @@ +Processing module test103 (test_input/test103.py)... + SyntaxError: invalid syntax (test_input/test103.py, line 4) + print ' '.join(str(x) for x in range(10)) + ^ + +Warnings... + +test_input/test103.py:1: NOT PROCESSED UNABLE TO IMPORT --- /dev/null +++ pychecker-0.8.19/test_expected/test68 @@ -0,0 +1,9 @@ +Processing module test68 (test_input/test68.py)... + +Warnings... + +test_input/test68.py:15: Function returns a value and also implicitly returns None +test_input/test68.py:44: Function returns a value and also implicitly returns None +test_input/test68.py:63: Function returns a value and also implicitly returns None +test_input/test68.py:128: Function returns a value and also implicitly returns None +test_input/test68.py:142: Function returns a value and also implicitly returns None --- /dev/null +++ pychecker-0.8.19/test_expected/test96 @@ -0,0 +1,6 @@ +Processing module test96 (test_input/test96.py)... + +Warnings... + +test_input/test96.py:7: string.find() returns an integer, consider checking >= 0 or < 0 for not found +test_input/test96.py:9: string.find() returns an integer, consider checking >= 0 or < 0 for not found --- /dev/null +++ pychecker-0.8.19/test_expected/test13 @@ -0,0 +1,6 @@ +Processing module test13 (test_input/test13.py)... + +Warnings... + +test_input/test13.py:7: Global variable (x) not defined in module scope +test_input/test13.py:25: No global (xxx) found --- /dev/null +++ pychecker-0.8.19/test_expected/test16 @@ -0,0 +1,5 @@ +Processing module test16 (test_input/test16.py)... + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/test_expected/test34-2.3 @@ -0,0 +1,17 @@ +Processing module test34 (test_input/test34.py)... + +Warnings... + +[system path]/getopt.py:42: No doc string for class GetoptError + +[system path]/locale.py:168: (str) shadows builtin +[system path]/locale.py:173: (str) shadows builtin + +test_input/test34.py:1: No doc string for class Error +test_input/test34.py:6: Module member (string) re-imported with * +test_input/test34.py:9: Using import and from ... import for (locale) +test_input/test34.py:10: Using import and from ... import for (locale) +test_input/test34.py:13: Using import and from ... import for (getopt) +test_input/test34.py:16: Using import and from ... import for (copy) +test_input/test34.py:19: Module member (from re import sub) re-imported +test_input/test34.py:22: Module (ihooks) re-imported --- /dev/null +++ pychecker-0.8.19/test_expected/test27 @@ -0,0 +1,7 @@ +Processing module test27 (test_input/test27.py)... +test_input/test27.py:12: SyntaxWarning: local name 'string' in 'd' shadows use of 'string' as global in nested scope 'lambda' + def d(lines): + +Warnings... + +None --- /dev/null +++ pychecker-0.8.19/pychecker2/VariableChecks.py @@ -0,0 +1,354 @@ +from pychecker2.Check import Check +from pychecker2.Options import Opt, BoolOpt +from pychecker2.Warning import Warning +from pychecker2.util import * +from pychecker2 import symbols + +from compiler import ast, walk + +def _is_method(scope): + return scope.__class__ is symbols.FunctionScope and \ + scope.parent.__class__ is symbols.ClassScope + +def _is_self(scope, name): + return _is_method(scope) and name in scope.node.argnames[:1] + +def is_arg_and_defaulted_to_same_name(name, scope): + if isinstance(scope, symbols.FunctionScope): + if name in scope.node.argnames and scope.node.defaults: + # compute default args + args = scope.node.argnames[:] + # knock off kwargs + if scope.node.kwargs: + args = args[:-1] + # knock off varags + if scope.node.varargs: + args = args[:-1] + # take the last args as the defaults + args = args[-len(scope.node.defaults):] + try: + # get the corresponding default arg value + default = scope.node.defaults[args.index(name)] + # must be a Name node of the same name + if isinstance(default, ast.Name) and \ + default.name == name: + return 1 + except ValueError: + pass + return None + + +class ShadowCheck(Check): + """Use symbol information to check that no scope defines a name + already known to a parent scope""" + + defineNone = Warning('Report any redefinition of None', + 'Do not redefine None') + shadowBuiltins = Warning('Report names that shadow builtins', + 'Identifier (%s) shadows builtin', 0) + shadowIdentifier = Warning('Report names already defined in outer scopes', + 'Identifier (%s) shadows definition in scope %s') + def check(self, file, unused_checker): + # warn if any name defined in a scope is defined in a parent scope + # or even the builtins + for node, scope in file.not_class_scopes(): + for name in scope.defs: + if name == 'None': + file.warning(scope.defs[name], self.defineNone) + continue + if name in scope.globals: + continue + if is_arg_and_defaulted_to_same_name(name, scope): + continue + if _is_self(scope, name): + continue + if __builtins__.has_key(name): + file.warning(scope.defs[name], self.shadowBuiltins, name) + for p in parents(scope): + if p.defs.has_key(name) and \ + not isinstance(p, symbols.ClassScope): + file.warning(scope.defs[name], \ + self.shadowIdentifier, name, `p`) + +def _str_value(s): + if type(s) == type(''): + return eval(s) + return s + + +def _empty_function(stmts): + if not stmts: + return 1 + stmt = stmts[0] + # functions which only raise exceptions + if isinstance(stmt, ast.Raise): + return 1 + # functions which do nothing + if len(stmts) == 1 and isinstance(stmt, ast.Pass): + return 1 + # functions which just return a constant + if len(stmts) == 1 and \ + isinstance(stmt, ast.Return) and isinstance(stmt.value, ast.Const): + return 1 + # functions which only assert falsehood + if isinstance(stmt, ast.Assert): + if (isinstance(stmt.test, ast.Const) and not stmt.test.value) or \ + (isinstance(stmt.test, ast.Name) and stmt.test.name == 'None'): + return 1 + return 0 + +class UnusedCheck(Check): + """Use symbol information to check that no scope defines a name + not used in this or any child scope""" + + unused = Warning('Report names not used', 'Identifier (%s) not used') + + def __init__(self): + self.reportUnusedSelf = None + self.unusedPrefixes = None + + def get_options(self, options): + desc = 'Ignore unused identifiers that start with these values' + default = ['unused', 'empty', 'dummy', + '__pychecker__', '__all__', '__version__', 'ignored'] + options.add(Opt(self, 'unusedPrefixes', desc, default)) + + desc = 'Ignore unused method "self" parameter' + options.add(BoolOpt(self, 'reportUnusedSelf', desc)) + + def check(self, file, unused_checker): + self.unusedPrefixes = _str_value(self.unusedPrefixes) + + def used(name, parent_scope): + if parent_scope.uses.has_key(name): + return 1 + for c in parent_scope.get_children(): + if used(name, c): + return 1 + return 0 + + for nodes, scope in file.not_class_scopes(): + if isinstance(nodes, ast.Function): + if _empty_function(nodes.code.nodes): + continue + + # ensure that every defined variable is used in some scope + for var in scope.defs: + # ignore '_'... just because + if var == '_': + continue + + # check for method self + if not self.reportUnusedSelf and _is_self(scope, var): + continue + + # ignore names in the root scope which are not imported: + # class defs, function defs, variables, etc, unless + # they start with '_' + if scope == file.root_scope: + if not scope.imports.has_key(var): + if not var.startswith('_'): + continue + + for prefix in self.unusedPrefixes: + if var.startswith(prefix): + break + else: + if not used(var, scope) and not scope.globals.has_key(var): + file.warning(scope.defs[var], self.unused, var) + +def _importedName(scope, name): + if scope.imports.has_key(name): + return 1 + if scope.parent: + return _importedName(scope.parent, name) + return None + +class UnknownCheck(Check): + """Use symbol information to check that no scope uses a name + not defined in a parent scope""" + + unknown = Warning('Report names that are not defined', + 'Unknown identifier: %s') + + builtins = {} + builtins.update(__builtins__) + builtins['__builtins__'] = __builtins__ + builtins['WindowsError'] = getattr(__builtins__, 'WindowsError', None) + + def check(self, file, unused_checker): + + # if a name used is not found in the defined variables, complain + for scope in file.scopes.values(): + unknown = dict_minus(scope.uses, scope.defs) + unknown = dict_minus(unknown, self.builtins) + for var in unknown: + for p in parents(scope): + if p.defs.has_key(var): + break + else: + if not _importedName(scope, var): + file.warning(scope.uses[var], self.unknown, var) + +def _first_arg_defaulted(function_node): + count = len(function_node.argnames) + if function_node.varargs: + count -= 1 + if function_node.kwargs: + count -= 1 + if count > 0 and len(function_node.defaults) == count: + return 1 + return None + +class SelfCheck(Check): + 'Check for simple self parameter' + + selfName = Warning('Report any methods whose first argument is not self', + 'First argument to method %s (%s) is not in %s') + selfDefault = Warning('Report a self parameter with a default value', + 'First argument to method %s (%s) has a default value') + + functionSelf = Warning('Report functions (not methods) with ' + 'arguments named "self"', + 'Argument to function (%s) is "%s"') + + missingSelf = Warning('Report methods without "self"', + 'Method %s is missing self parameter') + + def get_options(self, options): + desc = 'Name of self parameter' + default = ["self", "this", "s"] + options.add(Opt(self, 'selfNames', desc, default)) + + desc = 'Suspicious self parameters' + self.selfSuspicious = ["self"] + options.add(Opt(self, 'selfSuspicious', desc, self.selfSuspicious)) + + def check(self, file, unused_checker): + self.selfNames = _str_value(self.selfNames) + self.selfSuspicious = _str_value(self.selfSuspicious) + + for node, scope in file.function_scopes(): + args = node.argnames + name = getattr(scope.node, 'name', 'lambda') + if _is_method(scope): + if not args: + file.warning(scope.node, self.missingSelf, name) + else: + if args[0] not in self.selfNames: + file.warning(scope.node, self.selfName, + name, args[0], `self.selfNames`) + if _first_arg_defaulted(scope.node): + file.warning(scope.node, self.selfDefault, + name, args[0]) + else: + for arg in args: + if arg in self.selfSuspicious: + file.warning(scope.defs[arg], self.functionSelf, + name, arg) + + + +class UnpackCheck(Check): + 'Mark all unpacked variables as used' + + def __init__(self): + self.unpackedUsed = None + + def get_options(self, options): + desc = 'Do not treat variables used in tuple assignment as used' + options.add(BoolOpt(self, 'unpackedUsed', desc, 1)) + + def check(self, file, unused_checker): + if not self.unpackedUsed: + return + + class Visitor: + def visitAssTuple(self, node): + for c in node.getChildNodes(): + for n in parents(c): + try: + file.scopes[n].uses[c.name] = node + break + except (KeyError, AttributeError): + pass + visitAssList = visitAssTuple + + # local args unpacked on the `def' line are used, too + for scope_node, scope in file.function_scopes(): + for arg in type_filter(scope_node.argnames, tuple): + for unpacked in ast.flatten(arg): + scope.uses[unpacked] = scope.uses.get(unpacked, scope_node) + + if file.root_scope: + walk(file.root_scope.node, Visitor()) + +def intersect2(a, b): + return [i for i in a if i in b] + +def intersect(items): + result = items[0] + for item in items[1:]: + result = intersect2(result, item) + return result + +class UsedBeforeSetCheck(Check): + + usedBeforeDefined = \ + Warning('Report variables that may be used before they are defined', + 'The local %s may be used before defined') + + def check(self, file, unused_checker): + class Visitor(BaseVisitor): + def __init__(self, defines = None, uses = None): + # list of vars defined + self.defines = [] + # name->node vars used before defined + self.uses = {} + if defines is not None: + self.defines = defines[:] + if uses is not None: + self.uses = uses.copy() + def visitFunction(self, n): + self.defines.append(n.name) + + visitClass = visitFunction + visitAssName = visitFunction + + def visitGlobal(self, node): + for name in node.names: + self.defines.append(name) + + def visitListComp(self, n): + # visit qualifiers before expression + children = ast.flatten_nodes(n.quals) + [n.expr] + for c in children: + self.visit(c) + + def visitName(self, n): + if n.name not in self.defines: + self.uses[n.name] = self.uses.get(n.name, n) + + def visitIf(self, n): + if not n.else_: + return + visits = [] + for test, code in n.tests: + visits.append(walk(code, Visitor(self.defines, self.uses))) + visits.append(walk(n.else_, Visitor(self.defines, self.uses))) + # compute the intersection of defines + self.defines = intersect([v.defines for v in visits]) + # compute the union of uses, perserving first occurances + union = {} + visits.reverse() + for v in visits: + union.update(v.uses) + union.update(self.uses) + self.uses = union + + for node, scope in file.function_scopes(): + predefined = ast.flatten(scope.params) + scope.imports.keys() + visitor = walk(node.code, Visitor(predefined)) + usedBefore = dict_intersect(visitor.uses, scope.defs) + for name, use_node in usedBefore.items(): + file.warning(use_node, self.usedBeforeDefined, name) --- /dev/null +++ pychecker-0.8.19/pychecker2/OpChecks.py @@ -0,0 +1,68 @@ +from pychecker2.Check import Check +from pychecker2.Warning import Warning +from pychecker2.util import BaseVisitor + +import compiler + + +class OpCheck(Check): + + operator = Warning( + "Check for (++) and (--) which are legal, but not useful", + "Operator (%s) doesn't exist, statement has no effect" + ) + operatorPlus = Warning( + 'Check for unary +', + "Operator (+) normally has no effect" + ) + + def check(self, file, unused_checklist): + class OpVisitor: + def visitUnaryAdd(s, n): + if n.getChildren()[0].__class__ == compiler.ast.UnaryAdd: + file.warning(n, self.operator, '++') + else: + file.warning(n, self.operatorPlus) + + def visitUnarySub(s, n): + if n.getChildren()[0].__class__ == compiler.ast.UnarySub: + file.warning(n, self.operator, '--') + if file.parseTree: + compiler.walk(file.parseTree, OpVisitor()) + +class ExceptCheck(Check): + emptyExcept = Warning('Warn about "except:"', + 'Empty except clauses can hide unexpected errors') + + def check(self, file, unused_checklist): + class ExceptVisitor(BaseVisitor): + def visitTryExcept(s, node): + for exc, det, code in node.handlers: + if exc is None: + file.warning(code.nodes[0], self.emptyExcept) + s.visitChildren(node) + if file.parseTree: + compiler.walk(file.parseTree, ExceptVisitor()) + +class CompareCheck(Check): + useIs = Warning('warn about "== None"', + 'use "is" when comparing with None') + + def check(self, file, unused_checklist): + def checkEqualNone(node, expr, op): + if (op == '==' and + expr.__class__ == compiler.ast.Name and + expr.name == "None"): + file.warning(node, self.useIs) + + class CompareVisitor(BaseVisitor): + def visitCompare(s, node): + children = node.getChildren() + for i in range(0, len(children) - 1, 2): + left, op = children[i:i+2] + checkEqualNone(node, left, op) + op, right = children[-2:] + checkEqualNone(node, right, op) + + if file.parseTree: + compiler.walk(file.parseTree, CompareVisitor()) --- /dev/null +++ pychecker-0.8.19/pychecker2/ClassChecks.py @@ -0,0 +1,364 @@ +from pychecker2.Check import Check +from pychecker2.Check import Warning +from pychecker2 import symbols +from pychecker2.util import * + +from compiler.misc import mangle +from compiler import ast, walk + +_ignorable = {} +for ignore in ['repr', 'dict', 'class', 'doc', 'str']: + _ignorable['__%s__' % ignore] = 1 + +class GetDefs(BaseVisitor): + "Record definitions of a attribute of self, who's name is provided" + def __init__(self, name): + self.selfname = name + self.result = {} + + def visitAssAttr(self, node): + if isinstance(node.expr, ast.Name) and \ + node.expr.name == self.selfname and \ + isinstance(node.parent, (ast.Assign, ast.AssTuple)): + self.result[node.attrname] = node + + def visitClass(self, node): # ignore nested classes + pass + +class GetRefs(BaseVisitor): + "Record references to a attribute of self, who's name is provided" + def __init__(self, name): + self.selfname = name + self.result = {} + + def visitAssAttr(self, node): + if isinstance(node.expr, ast.Name) and \ + node.expr.name == self.selfname and \ + not isinstance(node.parent, (ast.Assign, ast.AssTuple)): + self.result[node.attrname] = node + self.visitChildren(node) + + def visitGetattr(self, node): + if isinstance(node.expr, ast.Name) and \ + node.expr.name == self.selfname: + self.result[node.attrname] = node + self.visitChildren(node) + + def visitClass(self, node): # ignore nested classes + pass + + +def _get_methods(class_scope): + return type_filter(class_scope.get_children(), symbols.FunctionScope) + +class NotSimpleName(Exception): pass + +# compress Getattr(Getattr(Name(x), y), z) -> "x.y.z" +def get_name(node): + if isinstance(node, ast.Getattr): + return get_name(node.expr) + (node.attrname, ) + elif isinstance(node, ast.Name): + return (node.name,) + else: + raise NotSimpleName + +def get_base_names(scope): + names = [] + for b in scope.node.bases: + try: + names.append(get_name(b)) + except NotSimpleName: # FIXME: hiding expressions + pass + return names + +def find_in_module(package, remotename, names, checker): + # No other names, must be a name from the module + if not names: + f = checker.check_module(package) + if f: + return find_scope_going_down(f.root_scope, [remotename], checker) + return None + + # complex name lookup + try: + # first, get the real name of the package + name = package.__name__ + module = __import__(name, globals(), {}, ['']) + except AttributeError: + # ok, so its a fake module... go with that + module = package + if remotename: + name += "." + remotename + # now import it, and chase down any other modules + submodule = getattr(module, names[0], None) + if type(submodule) == type(symbols): + return find_in_module(submodule, None, names[1:], checker) + + # object in the module is not another module, so chase down the source + f = checker.check_module(submodule) + if f: + return find_scope_going_down(f.root_scope, names, checker) + return None + +def find_scope_going_down(scope, names, checker): + "Drill down scopes to find definition of x.y.z" + for c in scope.get_children(): + if getattr(c, 'name', '') == names[0]: + if len(names) == 1: + return c + return find_scope_going_down(c, names[1:], checker) + # Not defined here, check for import + return find_imported_class(scope.imports, names, checker) + +def find_imported_class(imports, names, checker): + # may be defined by import + for i in range(1, len(names) + 1): + # try x, then x.y, then x.y.z as imported names + try: + name = ".".join(names[:i]) + ref = imports[name] + # now look for the rest of the name + result = find_in_module(ref.module, ref.remotename, names[i:], checker) + if result: + return result + except (KeyError, ImportError): + pass + return None + +def find_scope_going_up(scope, names, checker): + "Search up to find scope defining x of x.y.z" + for p in parents(scope): + if p.defs.has_key(names[0]): + return find_scope_going_down(p, names, checker) + # name imported via 'from module import *' + try: + return find_in_module(p.imports[names[0]].module, None, names, checker) + except KeyError: + return None + +def get_base_classes(scope, checker): + result = [] + for name in get_base_names(scope): + base = find_scope_going_up(scope, name, checker) + if base: + result.append(base) + result.extend(get_base_classes(base, checker)) + return result + +def conformsTo(a, b): + alen = len(a.node.argnames) + blen = len(b.node.argnames) + # f(a, *args, **kw) conforms to f(a, b, *args, **kw) + # f(a, *args) conforms to f(a, b, *args) + # f(a, *args) conforms to f(a, b, c) + # f(a, b, c, *args) does not conform to f(a, b) + if alen == blen: + if a.node.kwargs == b.node.kwargs and a.node.varargs == b.node.varargs: + return 1 + if a.node.varargs and alen - 1 <= blen: + return a.node.kwargs == b.node.kwargs + return None + +class AttributeCheck(Check): + "check `self.attr' expressions for attr" + + unknownAttribute = Warning('Report unknown object attributes in methods', + 'Class %s has no attribute %s') + unusedAttribute = Warning('Report attributes unused in methods', + 'Attribute %s is not used in class %s') + methodRedefined = Warning('Report the redefinition of class methods', + 'Method %s in class %s redefined') + signatureChanged = Warning('Report methods whose signatures do not ' + 'match base class methods', + 'Signature does not match method ' + '%s in base class %s') + attributeInitialized = \ + Warning('Report attributes not initialized in __init__', + 'Attribute %s is not initialized in __init__') + + def check(self, file, checker): + def visit_with_self(Visitor, method): + if not method.node.argnames: + return {} + return walk(method.node, Visitor(method.node.argnames[0])).result + + # for all class scopes + for node, scope in file.class_scopes(): + init_attributes = None # attributes initilized in __init__ + attributes = {} # "self.foo = " kinda things + methods = {} # methods -> scopes + + # get attributes defined on self + for m in _get_methods(scope): + defs = visit_with_self(GetDefs, m) + if m.name == '__init__': + init_attributes = defs + attributes.update(defs) + methods[mangle(m.name, scope.name)] = m + + # complain about attributes not initialized in __init__ + if init_attributes is not None: + for name, node in dict_minus(attributes, init_attributes).items(): + file.warning(node, self.attributeInitialized, name) + + # collect inherited gunk: methods and attributes + # check for non-conformant methods + inherited_methods = scope.defs.copy() + inherited_attributes = attributes.copy() + for base in get_base_classes(scope, checker): + for m in _get_methods(base): + inherited_attributes.update(visit_with_self(GetDefs, m)) + mname = mangle(m.name, base.name) + if m.name != "__init__" and \ + methods.has_key(mname) and \ + not conformsTo(methods[mname], m): + file.warning(methods[mname].node, + self.signatureChanged, m.name, base.name) + else: + methods[mname] = m + inherited_methods.update(base.defs) + + # complain about attributes with the same name as methods + both = dict_intersect(attributes, inherited_methods) + for name, node in both.items(): + file.warning(node, self.methodRedefined, name, scope.name) + + # find refs on self + refs = {} + for m in _get_methods(scope): + refs.update(visit_with_self(GetRefs, m)) + + # Now complain about refs on self that aren't known + unknown = dict_minus(refs, inherited_methods) + unknown = dict_minus(unknown, _ignorable) + unknown = dict_minus(unknown, scope.defs) + unknown = dict_minus(unknown, inherited_attributes) + for name, node in unknown.items(): + file.warning(node, self.unknownAttribute, scope.name, name) + + unused = dict_minus(attributes, refs) + for name, node in unused.items(): + if name.startswith('__'): + file.warning(node, self.unusedAttribute, name, scope.name) + +class GetReturns(BaseVisitor): + + def __init__(self): + self.result = [] + + def visitReturn(self, node): + self.result.append(node) + + def visitFunction(self, node): pass + visitClass = visitFunction + +class InitCheck(Check): + + initReturnsValue = Warning('Report value returned from __init__', + 'Method __init__ should not return a value') + + def check(self, file, unused_checker): + + for node, scope in file.class_scopes(): + for m in _get_methods(scope): + if m.name == '__init__': + for r in walk(m.node.code, GetReturns()).result: + if isinstance(r.value, ast.Const) and \ + r.value.value is None: + continue + if isinstance(r.value, ast.Name) and \ + r.value.name == 'None': + continue + file.warning(r, self.initReturnsValue) + + + +special = { + '__cmp__': 2, '__del__': 1, '__delitem__': 2, '__eq__': 2, + '__ge__': 2, '__getitem__': 2, '__gt__': 2, '__hash__': 1, + '__le__': 2, '__len__': 1, '__lt__': 2, '__ne__': 2, + '__nonzero__': 1, '__repr__': 1, '__setitem__': 3, '__str__': 1, + '__getattr__': 2, '__setattr__': 3, + '__delattr__': 2, '__len__': 1, '__delitem__': 2, '__iter__': 1, + '__contains__': 2,'__setslice__': 4,'__delslice__': 3, + '__add__': 2, '__sub__': 2, '__mul__': 2, '__floordiv__': 2, + '__mod__': 2, '__divmod__': 2, '__lshift__': 2, + '__rshift__': 2, '__and__': 2, '__xor__': 2, '__or__': 2, + '__div__': 2, '__truediv__': 2, '__radd__': 2, '__rsub__': 2, + '__rmul__': 2, '__rdiv__': 2, '__rmod__': 2, '__rdivmod__': 2, + '__rpow__': 2, '__rlshift__': 2, '__rrshift__': 2, '__rand__': 2, + '__rxor__': 2, '__ror__': 2, '__iadd__': 2, '__isub__': 2, + '__imul__': 2, '__idiv__': 2, '__imod__': 2, '__ilshift__': 2, + '__irshift__': 2, '__iand__': 2, '__ixor__': 2, '__ior__': 2, + '__neg__': 1, '__pos__': 1, '__abs__': 1, '__invert__': 1, + '__complex__': 1, '__int__': 1, '__long__': 1, '__float__': 1, + '__oct__': 1, '__hex__': 1, '__coerce__': 2, + '__new__': None, + '__getinitargs__': 1, '__reduce__': 1, + '__getstate__': 1,'__setstate__': 2, + '__copy__': 1, '__deepcopy__': 1, + '__pow__': 2, '__ipow__': 2, # 2 or 3 + '__call__': None, # any number > 1 + '__getslice__': 3, # deprecated + '__getattribute__': 2, + } + +def check_special(scope): + try: + count = special[scope.name] + max_args = len(scope.node.argnames) + min_args = max_args - len(scope.node.defaults) + if min_args > count or max_args < count or \ + scope.node.varargs or scope.node.kwargs: + return special[scope.name] + except KeyError: + pass + return None + +class SpecialCheck(Check): + + specialMethod = Warning('Report special methods with incorrect ' + 'number of arguments', + 'The %s method requires %d argument%s, ' + 'including self') + + notSpecial = Warning('Report methods with "__" prefix and suffix ' + 'which are not defined as special methods', + 'The method %s is not a special method, ' + 'but is reserved.') + + def check(self, file, unused_checker): + + for node, scope in file.class_scopes(): + for m in _get_methods(scope): + n = check_special(m) + if n: + file.warning(m.node, self.specialMethod, m.name, n, + n > 1 and "s" or "") + name = m.name + if name.startswith('__') and name.endswith('__') and \ + name != '__init__' and not special.has_key(name): + file.warning(m.node, self.notSpecial, name) + +class BackQuote(BaseVisitor): + + def __init__(self, selfname): + self.results = [] + self.selfname = selfname + + def visitBackquote(self, node): + if isinstance(node.expr, ast.Name) and node.expr.name == self.selfname: + self.results.append(node) + +class ReprCheck(Check): + + backquoteSelf = Warning('Report use of `self` in __repr__ methods', + 'Using `self` in __repr__') + def check(self, file, unused_checker): + for node, scope in file.class_scopes(): + for m in _get_methods(scope): + if m.name == '__repr__' and m.node.argnames: + visitor = BackQuote(m.node.argnames[0]) + for n in walk(m.node.code, visitor).results: + file.warning(n, self.backquoteSelf) + --- /dev/null +++ pychecker-0.8.19/pychecker2/util.py @@ -0,0 +1,73 @@ + +class BaseVisitor: + + def visit(self, unused_node): + "method is really overridden by compiler.visitor.ASTVisitor" + assert 0, 'Unreachable' + + def visitChildren(self, n): + for c in n.getChildNodes(): + self.visit(c) + +def try_if_exclusive(stmt_node1, stmt_node2): + from compiler import ast as ast + + """return true if the statements are in exclusive parts of if/elif/else + or try/finally/else""" + + parent = stmt_node1.parent.parent + if parent == stmt_node2.parent.parent: + if isinstance(parent, ast.If): + parts = [code for test, code in parent.tests] + parts.append(parent.else_) + for part in parts: + if part and stmt_node1 in part.nodes: + return stmt_node2 not in part.nodes + if isinstance(parent, ast.TryExcept): + parts = [] + if parent.body: + parts.extend(parent.body.nodes) + if parent.else_: + parts.extend(parent.else_.nodes) + return not (stmt_node1 in parts and stmt_node2 in parts) + return None + +def parents(obj): + class Parents: + def __init__(self, start): + self.next = start + def __call__(self): + retval = self.next.parent + self.next = retval + return retval + return iter(Parents(obj), None) + +def enclosing_scopes(scopes, node): + result = [] + n = node + while n: + try: + result.append(scopes[n]) + except KeyError: + pass + n = n.parent + return result + +def type_filter(seq, *classes): + return [s for s in seq if isinstance(s, classes)] + + +def dict_minus(a, b): + r = {} + for k, v in a.iteritems(): + if not b.has_key(k): + r[k] = v + return r + +def dict_intersect(a, b): + r = {} + for k, v in a.iteritems(): + if b.has_key(k): + r[k] = v + return r + --- /dev/null +++ pychecker-0.8.19/pychecker2/Options.py @@ -0,0 +1,106 @@ +class Error(Exception): pass + +class Opt: + + def __init__(self, object, longName, description, default): + self.object = object + self.longName = longName + self.description = description + setattr(object, longName, default) + self.default = default + + def set_value(self, value): + setattr(self.object, self.longName, value) + + def get_value(self): + return getattr(self.object, self.longName) + + def get_description(self): + return self.description + + def is_boolean(self): + return None + + def reset(self): + setattr(self.object, self.longName, self.default) + +class BoolOpt(Opt): + + def __init__(self, object, longName, description, default = None): + Opt.__init__(self, object, longName, description, default) + + def set_value(self, unused): + setattr(self.object, self.longName, not self.get_value()) + + def is_boolean(self): + return 1 + + +MAJOR = 'Major' +ERROR = 'Error' +MISC = 'Miscellaneous' +Categories = [MAJOR, ERROR, MISC] + +class Options: + + def __init__(self): + self.options = {} + for c in Categories: + self.options[c] = [] + self.add(BoolOpt(self, 'verbose', 'turn on verbose messages'), MISC) + self.add(BoolOpt(self, 'incremental', 'print warnings as they are created'), MISC) + self.add(BoolOpt(self, 'profile', 'print a profile of pychecker', 0), MISC) + + def add(self, option, category=ERROR): + self.options[category].append(option) + + def process_options(self, args): + import getopt + try: + longopts = {} + for opts in self.options.values(): + for opt in opts: + opt.reset() + optname = opt.longName + if opt.is_boolean() and opt.get_value(): + optname = "no-" + opt.longName + longopts[optname] = opt + specs = [] + for k, v in longopts.items(): + if not v.is_boolean(): + k += '=' + specs.append(k) + opts, args = getopt.getopt(args, '', specs) + except getopt.GetoptError, detail: + raise Error(detail) + + for opt, arg in opts: + longopts[opt[2:]].set_value(arg) + + from pychecker2.File import File + return [ File(f) for f in args ] + + def usage(self, argv0, stream): + indent = " " + over = 20 + print >> stream, "Usage:" + print >> stream, \ + "%s%s [options] [--] file1.py file2.py ..." % (indent, argv0) + print >> stream, "available options:" + for c in Categories: + if not self.options[c]: + continue + print >> stream + print >> stream, "%s:" % c + opts = self.options[c] + opts.sort(lambda x, y: cmp(x.longName, y.longName)) + for opt in opts: + name = opt.longName + if opt.is_boolean() and opt.get_value(): + name = "no-" + name + print >> stream, "%s--%*s %s" % ( + indent, -over, name, opt.get_description()) + if not opt.is_boolean(): + print >> stream, "%s %*s %s" % ( + indent, -over, '', opt.get_value()) + --- /dev/null +++ pychecker-0.8.19/pychecker2/Warning.py @@ -0,0 +1,13 @@ + +class Warning: + + def __init__(self, description, message, value = 1): + self.message = message + self.description = description + self.value = value + + def __cmp__(self, other): + return cmp(self.message, other.message) + + def __repr__(self): + return repr(self.message) --- /dev/null +++ pychecker-0.8.19/pychecker2/ReachableChecks.py @@ -0,0 +1,91 @@ +from pychecker2.Check import Check +from pychecker2.util import BaseVisitor +from pychecker2.Warning import Warning + +from compiler import ast, walk + +class ReachableCheck(Check): + + unreachable = Warning('Report unreachable code', 'Line is unreachable') + + implicitReturn = \ + Warning('Report implicit return in a function with explicit returns', + 'Function %s uses both implicit and explicit returns') + + def check(self, file, unused_checker): + class ReturnsVisitor(BaseVisitor): + def __init__(s): + s.always_returns = 0 # icky: result value by side-effect + s.has_returns = 0 + + def check_returns(s, node): + s.always_returns = 0 + s.visit(node) + return s.always_returns + + def alternatives_with_else(s, nodes, else_): + for n in nodes: + if not s.check_returns(n): + return + s.always_returns = 0 + if else_: + s.visit(else_) + + def visitAssert(s, node): + if isinstance(node.test, ast.Const): + s.always_returns = not node.test.value + if isinstance(node.test, ast.Name): + if node.test.name == 'None': + s.always_returns = 1 + + def visitReturn(s, node): + s.always_returns = 1 + if not isinstance(node.value, ast.Const) or \ + node.value.value is not None: + s.has_returns = 1 + + def visitRaise(s, unused_node): + s.always_returns = 1 + + def visitTryExcept(s, node): + # if body always returns, else code is unreachable + if s.check_returns(node.body) and node.else_: + file.warning(node.else_.nodes[0], self.unreachable) + s.always_returns = 0 + # no matter what happens in the try clause, it might + # cause an exception, so check the handlers and else + # conditions all return + handlers = [code for exc, detail, code in node.handlers] + s.alternatives_with_else(handlers, node.else_ or node.body) + + def visitIf(s, node): + code = [code for cond, code in node.tests] + s.alternatives_with_else(code, node.else_) + + def visitStmt(s, node): + for n in range(len(node.nodes) - 1): + if s.check_returns(node.nodes[n]): + file.warning(node.nodes[n + 1], self.unreachable) + break + else: + if node.nodes and \ + not s.check_returns(node.nodes[-1]) and \ + isinstance(node.parent, ast.Function) and \ + s.has_returns: + file.warning(node.nodes[-1], self.implicitReturn, + node.parent.name) + + def visitFunction(s, node): + pass + visitClass = visitFunction + + def visitWhile(s, unused): + # FIXME: while's may never execute and not return + s.always_returns = 0 + + visitFor = visitWhile + + for scope in file.scopes.values(): + if isinstance(scope.node, ast.Function): + walk(scope.node.code, ReturnsVisitor()) + --- /dev/null +++ pychecker-0.8.19/pychecker2/ReturnChecks.py @@ -0,0 +1,43 @@ +from pychecker2.Check import Check +from pychecker2.Check import Warning +from pychecker2.util import BaseVisitor, type_filter +from pychecker2 import symbols + +from compiler import ast, walk + +class Returns(BaseVisitor): + + def __init__(self): + self.result = [] + + def visitReturn(self, node): + self.result.append(node) + + # Don't descend into other scopes + def visitFunction(self, node): pass + visitClass = visitFunction + visitLambda = visitFunction + +def _is_implicit(node): + if isinstance(node, ast.Const) and node.value is None: + return 1 + return None + +class MixedReturnCheck(Check): + + mixedReturns = \ + Warning('Report functions using "return" and "return value"', + 'Function %s uses both "return" and "return value"') + + def check(self, file, unused_checker): + for scope in type_filter(file.scopes.values(), symbols.FunctionScope): + returns = walk(scope.node.code, Returns()).result + empty, value = [], [] + for node in returns: + if _is_implicit(node.value): + empty.append(node) + else: + value.append(node) + if len(empty) > 0 and len(value) > 0: + file.warning(empty[0], self.mixedReturns, scope.name) + --- /dev/null +++ pychecker-0.8.19/pychecker2/__init__.py @@ -0,0 +1 @@ +"" --- /dev/null +++ pychecker-0.8.19/pychecker2/symbols.py @@ -0,0 +1,372 @@ +####################################################################### +# +# THIS FILE IS __NOT__ under the pychecker copyright. +# +# The majority of this file is from the python2.2 distribution. +# It is under the python2.2 copyright. +# +####################################################################### + +"""Module symbol-table generator""" + +from compiler import ast +from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN +from compiler.misc import mangle +import types + +import sys + +MANGLE_LEN = 256 + +class Scope: + # XXX how much information do I need about each name? + def __init__(self, name, module, klass=None): + self.name = name + self.module = module + self.defs = {} + self.uses = {} + self.globals = {} + self.params = {} + self.frees = {} + self.cells = {} + self.children = [] + # nested is true if the class could contain free variables, + # i.e. if it is nested within another function. + self.nested = None + self.generator = None + self.klass = None + if klass is not None: + for i in range(len(klass)): + if klass[i] != '_': + self.klass = klass[i:] + break + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.name) + + def mangle(self, name): + if self.klass is None: + return name + return mangle(name, self.klass) + + def add_def(self, name, node): + self.defs[self.mangle(name)] = node + + def add_use(self, name, node): + name = self.mangle(name) + self.uses[name] = self.uses.get(name, node) + + def add_global(self, name, node): + name = self.mangle(name) + if self.uses.has_key(name) or self.defs.has_key(name): + pass # XXX warn about global following def/use + if self.params.has_key(name): + raise SyntaxError, "%s in %s is global and parameter" % \ + (name, self.name) + self.globals[name] = None + self.module.add_def(name, node) + + def add_param(self, name, node): + name = self.mangle(name) + self.defs[name] = node + self.params[name] = node + + def get_names(self): + d = {} + d.update(self.defs) + d.update(self.uses) + d.update(self.globals) + return d.keys() + + def add_child(self, child): + self.children.append(child) + + def get_children(self): + return self.children + + def DEBUG(self): + print >> sys.stderr, self.name, self.nested and "nested" or "" + print >> sys.stderr, "\tglobals: ", self.globals + print >> sys.stderr, "\tcells: ", self.cells + print >> sys.stderr, "\tdefs: ", self.defs + print >> sys.stderr, "\tuses: ", self.uses + print >> sys.stderr, "\tfrees:", self.frees + + def check_name(self, name): + """Return scope of name. + + The scope of a name could be LOCAL, GLOBAL, FREE, or CELL. + """ + if self.globals.has_key(name): + return SC_GLOBAL + if self.cells.has_key(name): + return SC_CELL + if self.defs.has_key(name): + return SC_LOCAL + if self.nested and (self.frees.has_key(name) or + self.uses.has_key(name)): + return SC_FREE + if self.nested: + return SC_UNKNOWN + else: + return SC_GLOBAL + + def get_free_vars(self): + if not self.nested: + return {} + free = {} + free.update(self.frees) + for name in self.uses.keys(): + if not (self.defs.has_key(name) or + self.globals.has_key(name)): + free[name] = self.uses[name] + return free + + def handle_children(self): + for child in self.children: + frees = child.get_free_vars() + globals = self.add_frees(frees) + for name, node in globals.items(): + child.force_global(name, node) + + def force_global(self, name, node): + """Force name to be global in scope. + + Some child of the current node had a free reference to name. + When the child was processed, it was labelled a free + variable. Now that all its enclosing scope have been + processed, the name is known to be a global or builtin. So + walk back down the child chain and set the name to be global + rather than free. + + Be careful to stop if a child does not think the name is + free. + """ + self.globals[name] = node + if self.frees.has_key(name): + del self.frees[name] + for child in self.children: + if child.check_name(name) == SC_FREE: + child.force_global(name, node) + + def add_frees(self, names): + """Process list of free vars from nested scope. + + Returns a list of names that are either 1) declared global in the + parent or 2) undefined in a top-level parent. In either case, + the nested scope should treat them as globals. + """ + child_globals = {} + for name, node in names.items(): + sc = self.check_name(name) + if self.nested: + if sc == SC_UNKNOWN or sc == SC_FREE \ + or isinstance(self, ClassScope): + self.frees[name] = node + elif sc == SC_GLOBAL: + child_globals[name] = node + elif isinstance(self, FunctionScope) and sc == SC_LOCAL: + self.cells[name] = node + elif sc != SC_CELL: + child_globals[name] = node + else: + if sc == SC_LOCAL: + self.cells[name] = node + elif sc != SC_CELL: + child_globals[name] = node + return child_globals + + def get_cell_vars(self): + return self.cells.keys() + +class ModuleScope(Scope): + __super_init = Scope.__init__ + + def __init__(self): + self.__super_init("global", self) + +class FunctionScope(Scope): + pass + +class LambdaScope(FunctionScope): + __super_init = FunctionScope.__init__ + + __counter = 1 + + def __init__(self, module, klass=None): + i = self.__counter + self.__counter += 1 + self.__super_init("lambda.%d" % i, module, klass) + +class ClassScope(Scope): + __super_init = Scope.__init__ + + def __init__(self, name, module): + self.__super_init(name, module, name) + +class SymbolVisitor: + def __init__(self): + self.scopes = {} + self.klass = None + + # node that define new scopes + def visit(self, unused_node, *args): + "overwritten by compiler.walk" + pass + + def visitModule(self, node): + scope = self.module = self.scopes[node] = ModuleScope() + self.visit(node.node, scope) + + visitExpression = visitModule + + def visitFunction(self, node, parent): + parent.add_def(node.name, node) + for n in node.defaults: + self.visit(n, parent) + scope = FunctionScope(node.name, self.module, self.klass) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + self.scopes[node] = scope + self._do_args(scope, node.argnames, node) + self.visit(node.code, scope) + self.handle_free_vars(scope, parent) + + def visitLambda(self, node, parent): + for n in node.defaults: + self.visit(n, parent) + scope = LambdaScope(self.module, self.klass) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + self.scopes[node] = scope + self._do_args(scope, node.argnames, node) + self.visit(node.code, scope) + self.handle_free_vars(scope, parent) + + def _do_args(self, scope, args, node): + for name in args: + if type(name) == types.TupleType: + self._do_args(scope, name, node) + else: + scope.add_param(name, node) + + def handle_free_vars(self, scope, parent): + parent.add_child(scope) + scope.handle_children() + + def visitClass(self, node, parent): + parent.add_def(node.name, node) + for n in node.bases: + self.visit(n, parent) + scope = ClassScope(node.name, self.module) + if parent.nested or isinstance(parent, FunctionScope): + scope.nested = 1 + self.scopes[node] = scope + prev = self.klass + self.klass = node.name + self.visit(node.code, scope) + self.klass = prev + self.handle_free_vars(scope, parent) + + # name can be a def or a use + + # XXX a few calls and nodes expect a third "assign" arg that is + # true if the name is being used as an assignment. only + # expressions contained within statements may have the assign arg. + + def visitName(self, node, scope, assign=0): + if assign: + scope.add_def(node.name, node) + else: + scope.add_use(node.name, node) + + # operations that bind new names + + def visitFor(self, node, scope): + self.visit(node.assign, scope, 1) + self.visit(node.list, scope) + self.visit(node.body, scope) + if node.else_: + self.visit(node.else_, scope) + + def visitFrom(self, node, scope): + for name, asname in node.names: + if name == "*": + continue + scope.add_def(asname or name, node) + + def visitImport(self, node, scope): + for name, asname in node.names: + i = name.find(".") + if i > -1: + name = name[:i] + scope.add_def(asname or name, node) + + def visitGlobal(self, node, scope): + for name in node.names: + scope.add_global(name, node) + + def visitAssign(self, node, scope): + """Propagate assignment flag down to child nodes. + + The Assign node doesn't itself contains the variables being + assigned to. Instead, the children in node.nodes are visited + with the assign flag set to true. When the names occur in + those nodes, they are marked as defs. + + Some names that occur in an assignment target are not bound by + the assignment, e.g. a name occurring inside a slice. The + visitor handles these nodes specially; they do not propagate + the assign flag to their children. + """ + for n in node.nodes: + self.visit(n, scope, 1) + self.visit(node.expr, scope) + + def visitAssName(self, node, scope, unused_assign=1): + scope.add_def(node.name, node) + + def visitAssAttr(self, node, scope, unused_assign=0): + self.visit(node.expr, scope, 0) + + def visitSubscript(self, node, scope, unused_assign=0): + self.visit(node.expr, scope, 0) + for n in node.subs: + self.visit(n, scope, 0) + + def visitSlice(self, node, scope, unused_assign=0): + self.visit(node.expr, scope, 0) + if node.lower: + self.visit(node.lower, scope, 0) + if node.upper: + self.visit(node.upper, scope, 0) + + def visitAugAssign(self, node, scope): + # If the LHS is a name, then this counts as assignment. + # Otherwise, it's just use. + self.visit(node.node, scope) + if isinstance(node.node, ast.Name): + self.visit(node.node, scope, 1) # XXX worry about this + self.visit(node.expr, scope) + + # prune if statements if tests are false + + _const_types = types.StringType, types.IntType, types.FloatType + + def visitIf(self, node, scope): + for test, body in node.tests: + if isinstance(test, ast.Const): + if type(test.value) in self._const_types: + if not test.value: + continue + self.visit(test, scope) + self.visit(body, scope) + if node.else_: + self.visit(node.else_, scope) + + # a yield statement signals a generator + + def visitYield(self, node, scope): + scope.generator = 1 + self.visit(node.value, scope) + --- /dev/null +++ pychecker-0.8.19/pychecker2/ParseChecks.py @@ -0,0 +1,84 @@ +from pychecker2.Check import Check +from pychecker2.Warning import Warning +from pychecker2.Options import BoolOpt +from pychecker2 import symbols + +from compiler import parseFile, walk +import parser + +def _parent_link(node): + for c in node.getChildNodes(): + c.parent = node + _parent_link(c) + +class ParseCheck(Check): + + syntaxErrors = Warning('Report/ignore syntax errors', + 'Unable to parse: %s') + + def __init__(self): + self.main = None + + def get_options(self, options): + desc = 'Ignore module-level code protected by __name__ == "__main__"' + options.add(BoolOpt(self, 'main', desc, 1)) + + def check(self, file, unused_checker): + try: + file.parseTree = parseFile(file.name) + # link each node to it's parent + _parent_link(file.parseTree) + file.parseTree.parent = None + except parser.ParserError, detail: + file.warning(1, self.syntaxErrors, detail.args[0]) + except IOError, detail: + file.warning(0, self.syntaxErrors, detail.strerror) + if not file.parseTree: + return + + if not self.main: + # remove __name__ == '__main__' code from module-level + for n in file.parseTree.node.nodes: + try: + test, code = n.tests[0] + comparison, value = test.ops[0] + if comparison == '==': + try: + if test.expr.name == '__name__' and \ + value.value == '__main__': + file.parseTree.node.nodes.remove(n) + break + except AttributeError: + if test.expr.value == '__main__' and \ + value.name == '__name__': + file.parseTree.node.nodes.remove(n) + break + except (AttributeError, IndexError): + pass + + file.scopes = walk(file.parseTree, symbols.SymbolVisitor()).scopes + file.root_scope = file.scopes[file.parseTree] + + # add starting lineno into scopes, since they don't have it + for k, v in file.scopes.items(): + v.lineno = k.lineno + + # define the root of the scope tree (global scope, within + # the module) + file.root_scope.lineno = 1 + + # create a mapping from scopes back to the nodes which made 'em + for node, scope in file.scopes.items(): + scope.node = node + + # create a mapping from each scope back to it's enclosing scope + for s in file.scopes.values(): + for c in s.get_children(): + c.parent = s + file.root_scope.parent = None + + # initialize the mapping of imported names to modules + for s in file.scopes.values(): + s.imports = {} + + --- /dev/null +++ pychecker-0.8.19/pychecker2/test.py @@ -0,0 +1,55 @@ +import os +import sys +import unittest +import glob + +def test(modules, verbosity): + for m in modules: + s = unittest.defaultTestLoader.loadTestsFromName(m) + result = unittest.TextTestRunner(verbosity=verbosity).run(s) + if not result.wasSuccessful(): + return 1 + return 0 + + +def _modules(root): + modules = [] + files = glob.glob(os.path.join(root, 'utest', '*.py')) + files.sort() + for fname in files: + fname = os.path.split(fname)[1] # remove path + module = 'pychecker2.utest.' + os.path.splitext(fname)[0] + if not module.endswith('_'): # ignore __init__ + modules.append(module) + return modules + +class Usage(Exception): pass + +def main(args): + import getopt + verbosity = 1 + try: + opts, files = getopt.getopt(args, 'v') + for opt, arg in opts: + if opt == '-v': + verbosity += 1 + else: + raise Usage('unknown option ' + opt) + except getopt.GetoptError, detail: + raise Usage(str(detail)) + + root = os.path.dirname(os.path.realpath(sys.argv[0])) + pychecker2 = os.path.split(root)[0] + sys.path.append(pychecker2) + + return test(_modules(root), verbosity) + + +if __name__ == '__main__': + try: + sys.exit(main(sys.argv[1:])) + except Usage, error: + err = sys.stderr + print >>err, "Error: " + str(error) + print >>err, "Usage: %s [-v]" % sys.argv[0] + sys.exit(1) --- /dev/null +++ pychecker-0.8.19/pychecker2/ConditionalChecks.py @@ -0,0 +1,44 @@ +from pychecker2.Check import Check +from pychecker2.util import BaseVisitor + +from compiler import ast, walk + +class ConstantFinder(BaseVisitor): + + def __init__(self): + self.result = [] + + def visitConst(self, node): + if isinstance(node.parent, (ast.Or, ast.Not, ast.And)): + self.result.append((node, `node.value`)) + + def visitName(self, node): + if node.name == 'None': + if isinstance(node.parent, (ast.Or, ast.Not, ast.And)): + self.result.append((node, 'None')) + +class GetConditionalConstants(BaseVisitor): + + def __init__(self): + self.result = [] + + def visitIf(self, node): + for test, code in node.tests: + self.result.extend(walk(test, ConstantFinder()).result) + + def visitWhile(self, node): + self.result.extend(walk(node.test, ConstantFinder()).result) + visitListCompIf = visitWhile + visitAssert = visitWhile + +class ConstantCheck(Check): + + constantInConditional = \ + Warning('Report constants used in conditionals', + 'Constant used in conditional %s') + + def check(self, file, unused_checker): + if file.parseTree: + v = GetConditionalConstants() + for n, value in walk(file.parseTree, v).result: + file.warning(n, self.constantInConditional, value) --- /dev/null +++ pychecker-0.8.19/pychecker2/NOTES.txt @@ -0,0 +1,131 @@ +This is a re-write of pychecker using traditional parse tree +techniques, rather than the bytecode. + +There are some other design changes, related to Warning objects and +Option handling. In general, pychecker2 tries to distribute checks to +separate classes. These classes are more self-contained: they hold +onto the option variables and define the Warning objects they support. + +ToDo: + All missing stuff + Always returning None + It is illegal to delete a name from the local namespace if it occurs + as a free variable in a nested block. + More path analysis + used before set for if/else try/except + Warn about unpacking args: + def f(a, (b, c)): pass + +Items still missing: + Error suppression (errors may be suppressed globally) + + Detail of exception is an exception + Local used after deleted, already deleted, deleted before set + Not calling base class __init__ + Using return value which is always None + Wrong # of args on function (including ctor) + Function arguments, kwargs + Abstract methods + exec may use locals/globals + import x with from x import + + Modifying a default parameter + Tuple access to list list[1, 2] + List .append() takes one argument + Return None from __getattr__ + string iteration + Inconsistent return type + Object has no attr + Method read as attribute, but not called: + Function always returns None (use empty return) + Unpack wrong size + Unpack wrong type + + Exec warnings + Security warning: input() + + Module imports itself + Complexity + Doc strings + New python features: + slots + properties + integer division + Warning for string raising + +Bugs: + More member not used + Speed + Is __file__ a builtin? + + Aliases: + class C: + def f(a, b): pass + def g(a, b): pass + h = f + h = g # redef of h, not caught now + + foo = 1 + del foo # should not be unused + + from __future__ import produces unused warnings + import of readline has side effect on input/raw_input, and should be + marked as used + +Important stuff: + +If you want to add new checks, there are some parts to be aware of: + + File + A stupid data structure to hold everything we know about + a file to be checked. + + Members: + name + The file name. + + parseTree + The root of the Abstract Syntax Tree returned from + compiler.parseFile. Will be None if the file + won't even parse. + + scopes + A dictionary of { node, scope } computed with + from compiler.symbols. For convenience, scopes + also refer back to the node and to the + enclosing parent scope (node and parent, + respectively). + + root_scope + Convience for scopes[parseTree] + + Check + Basic step for checking a file. Usually contributes + Warnings or additional information to File. New checks + will subclass this, and be added to the chain of checks + given in main(). + + Warning + A description of a warning emitted by pychecker. + + CheckList + Contains "global" check information: cached module + data and the list of Check objects. + + Command line options are pulled from each check. + A Warning is also turned into a boolean-style command line option. + +To add a new check, write a class (e.g., CompareCheck) that subclasses the +Check class. In its check method if you need to visit nodes of a particular +type, write a Visitor class (subclass of BaseVisitor) which has a +visit method, where is the name of a type of node to visit. +See + + http://www.python.org/~jeremy/compiler/module-compiler.ast.html + +for the types of the nodes or print file.parseTree to see what classes all +the nodes are. See the OpChecks.CompareCheck class for an example of a +check that visits all Compare nodes and the OpChecksExceptCheck class for an +example that visits all TryExcept nodes. + +New checks should have unit tests in utest/. --- /dev/null +++ pychecker-0.8.19/pychecker2/FormatStringChecks.py @@ -0,0 +1,183 @@ +from pychecker2.Check import Check +from pychecker2.util import BaseVisitor +from pychecker2.Warning import Warning +from compiler import ast, walk +from types import * +import re + +class UnknownError(Exception): pass + +def _compute_node(node, recurse): + if isinstance(node, ast.Add): + return recurse(node.left) + recurse(node.right) + elif isinstance(node, ast.Mul): + return recurse(node.left) * recurse(node.right) + elif isinstance(node, ast.Sub): + return recurse(node.left) - recurse(node.right) + elif isinstance(node, ast.Div): + return recurse(node.left) / recurse(node.right) + raise UnknownError + +def _compute_constant(node): + "Compute a simple forms of constant strings from an expression node" + if isinstance(node, ast.Const): + return node.value + return _compute_node(node, _compute_constant) + +def _compute_tuple_size(node): + "Compute the length of simple forms of tuples from an expression node" + if isinstance(node, ast.Tuple): + return (None,) * len(node.nodes) + if isinstance(node, ast.Const): + return node.value + if isinstance(node, ast.Backquote): + return '' + return _compute_node(node, _compute_tuple_size) + +# for details: http://www.python.org/doc/current/lib/typesseq-strings.html +_MOD_AND_TYPE = '([hlL])?([diouxXeEfFgGcrs%])' +_TUP_FORMAT_REGEX = re.compile('%(())?[ #+-]*' + '([0-9]*|[*])(|[.](|[*]|[0-9]*))' + + _MOD_AND_TYPE) +_DICT_FORMAT_REGEX = re.compile('%([(]([a-zA-Z_]+)[)])?[ #+-]*' + '([0-9]*)(|[.](|[0-9]*))' + _MOD_AND_TYPE) + +class FormatError(Exception): + def __init__(self, position): + Exception.__init__(self) + self.position = position + +def _check_format(s): + pos = 0 + specs = [] + while 1: + pos = s.find('%', pos) + if pos < 0: + return specs + + match = _TUP_FORMAT_REGEX.search(s, pos) + if not match or match.start(0) != pos: + match = _DICT_FORMAT_REGEX.search(s, pos) + if not match or match.start(0) != pos: + raise FormatError(pos) + + if match.group(7) != '%': # ignore "%%" + specs.append( (match.group(2), match.group(3), match.group(5), + match.group(6)) ) + pos = match.end(0) + return specs + +class _GetMod(BaseVisitor): + def __init__(self): + self.mods = [] + def visitMod(self, node): + self.mods.append(node) + self.visitChildren(node) + # don't descend into other scopes + def visitFunction(self, node): pass + visitClass = visitFunction + visitLambda = visitFunction + +def get_mods(node): + try: + return walk(node.code, _GetMod()).mods + except AttributeError: + return walk(node.node, _GetMod()).mods + +_BAD_FORMAT_MAX = 10 +def _bad_format_str(s, pos): + result = s[pos : pos + _BAD_FORMAT_MAX] + return result + (len(s) > pos + _BAD_FORMAT_MAX and "..." or "") + +class FormatStringCheck(Check): + "Look for warnings in format strings" + + badFormat = \ + Warning('Report illegal format specifications in format strings', + 'Bad format specifier at position %d (%s)') + uselessModifier = \ + Warning('Report unused modifiers for format strings (l, h, L)', + 'Modifier %s is not necessary') + + mixedFormat = \ + Warning('Report format strings which use both positional ' + 'and named formats', + 'Cannot mix positional and named formats (%%%s)') + + formatCount = \ + Warning('Report positional format string with the wrong ' + 'number of arguments', + 'Wrong number of arguments supplied for format: ' + '%d given %d required') + unknownFormatName = \ + Warning('Report unknown names if locals() or globals() ' + 'are used for format strings', + 'The name "%s" is not defined in %s') + + badConstant = \ + Warning('Report bad constant expressions for format strings', + 'Error computing constant: %s') + + def check(self, file, unused_checker): + if not file.parseTree: + return + + for scope in file.scopes.values(): + for mod in get_mods(scope.node): + formats = [] + try: + s = _compute_constant(mod.left) + formats = _check_format(s) + except FormatError, detail: + file.warning(mod, self.badFormat, detail.position, + _bad_format_str(s, detail.position)) + except TypeError, detail: + file.warning(mod, self.badConstant, str(detail)) + except UnknownError: + pass + if not formats: + continue + + count = len(formats) + for name, width, precision, lmodifier in formats: + if lmodifier: + file.warning(mod, self.uselessModifier, lmodifier) + if width == '*': + count += 1 + if precision == '*': + count += 1 + + names = [f[0] for f in formats if f[0]] + if len(names) == 0: # tuple + try: + t = _compute_tuple_size(mod.right) + n = 1 + if type(t) == TupleType: + n = len(t) + if n != count: + file.warning(mod, self.formatCount, n, count) + except UnknownError: + pass + except TypeError, detail: + file.warning(mod, self.badConstant, str(detail)) + + elif len(names) == len(formats): # dictionary + defines = None + if isinstance(mod.right, ast.CallFunc) and \ + isinstance(mod.right.node, ast.Name): + if mod.right.node.name in ['locals', 'vars']: + defines = scope.defs + uses = scope.uses + if mod.right.node.name == 'globals': + defines = file.root_scope.defs + uses = file.root_scope.uses + if defines is not None: + for n in names: + if not defines.has_key(n): + file.warning(mod, self.unknownFormatName, + n, mod.right.node.name) + else: + uses[n] = uses.get(n, mod) + else: + file.warning(mod, self.mixedFormat, "(%s)" % names[0]) + --- /dev/null +++ pychecker-0.8.19/pychecker2/TestSupport.py @@ -0,0 +1,57 @@ +from pychecker2 import main +from pychecker2 import Options + +import unittest + +class WarningTester(unittest.TestCase): + def __init__(self, arg): + unittest.TestCase.__init__(self, arg) + self.options = Options.Options() + self.checklist = main.create_checklist(self.options) + self.argv = [] + + def check_warning(self, w, expected_line, expected_type, *expected_args): + warn_line, warn_type, warn_args = w + try: + self.assertEqual(warn_type, expected_type) + self.assertEqual(warn_line, expected_line) + self.assertEqual(len(warn_args), len(expected_args)) + for i in range(len(expected_args)): + self.assertEqual(warn_args[i], expected_args[i]) + except AssertionError: # help w/debugging + print warn_line, warn_type, warn_args + print expected_line, expected_type, expected_args + raise + + def check_file(self, data): + import tempfile, os + fname = tempfile.mktemp() + fp = open(fname, 'wb') + try: + fp.write(data) + fp.close() + f, = self.options.process_options(self.argv + [fname]) + self.checklist.check_file(f) + finally: + fp.close() + os.unlink(fname) + return f + + def warning_file(self, f, line, warning, *args): + assert len(f.warnings) == 1, "Not just one warning:" + `f.warnings` + self.check_warning(f.warnings[0], line, warning, *args) + + def warning(self, test, line, warning, *args): + test += '\n' + f = self.check_file(test) + self.warning_file(f, line, warning, *args) + + def silent(self, test): + f = self.check_file(test) + if f.warnings: + print f.warnings + self.assertEqual(len(f.warnings), 0) + + def setUp(self): + self.argv = [] + --- /dev/null +++ pychecker-0.8.19/pychecker2/ScopeChecks.py @@ -0,0 +1,28 @@ + +from pychecker2.Check import Check +from pychecker2.Warning import Warning +from pychecker2 import util + +from compiler.ast import * + +class RedefineCheck(Check): + redefinedScope = Warning('Report redefined scopes', + 'Scope (%s) is redefined at line %d') + + def check(self, file, unused_checker): + names = {} # map name, parent to this scope + for node, scope in file.scopes.items(): + if hasattr(node, 'name'): # classes, functions + key = (scope.parent, node.name) + if names.has_key(key): + # oops, another scope has the same name and parent + first = node + second = names[key] + # but don't warn if the parent node is the same If or Try + if util.try_if_exclusive(first, second): + continue + if first.lineno > second.lineno: + second, first = first, second + file.warning(first, self.redefinedScope, + first.name, second.lineno) + names[key] = node --- /dev/null +++ pychecker-0.8.19/pychecker2/Check.py @@ -0,0 +1,96 @@ + +from pychecker2.Warning import Warning +from pychecker2.File import File +from pychecker2 import Options + +import time +import os +import stat + +class WarningOpt(Options.BoolOpt): + __pychecker__ = 'no-callinit' + + def __init__(self, longName, warning): + self.warning = warning + self.longName = longName + self.default = warning.value + + def set_value(self, unused): + self.warning.value = not self.warning.value + + def get_value(self): + return self.warning.value + + def get_description(self): + return self.warning.description + + def reset(self): + self.warning.value = self.default + +class CheckList: + + def __init__(self, checks): + self.checks = checks + self.modules = {} + + def check_file(self, f): + for c in self.checks: + c.check(f, self) + + def check_module(self, m): + f = None + try: + f = self.modules[m] + except KeyError: + import inspect + try: + fname = inspect.getsourcefile(m) + if fname: + f = File(fname) + except TypeError: + pass + self.modules[m] = f + if f: + self.check_file(f) + return f + + def __getstate__(self): + modules = [] + for k, v in self.modules.items(): + modules.append( (k.__name__, v) ) + return (time.time(), self.checks, modules) + + def __setstate__(self, data): + import inspect + cache_time, self.checks, modules = data + self.modules = {} + for k, v in modules: + module = __import__(k, globals(), {}, ['']) + # Don't recover files that are newer than the save time + try: + fname = inspect.getsourcefile(module) + last_modified = os.stat(fname)[stat.ST_MTIME] + except TypeError: + last_modified = 0 + + if last_modified < cache_time: + self.modules[module] = v + +class Check: + + def __str__(self): + return self.__class__.__name__ + + def get_warnings(self, options): + for attr in vars(self.__class__): + object = getattr(self, attr) + if isinstance(object, Warning): + options.add(WarningOpt(attr, object)) + + def get_options(self, options): + pass + + def check(self, file, checker): + pass + + --- /dev/null +++ pychecker-0.8.19/pychecker2/main.py @@ -0,0 +1,115 @@ +import sys +from os.path import dirname, realpath +sys.path.append(dirname(dirname(realpath(sys.argv[0])))) + +from pychecker2.Check import CheckList + +from pychecker2 import Options +from pychecker2 import ParseChecks +from pychecker2 import OpChecks +from pychecker2 import VariableChecks +from pychecker2 import ScopeChecks +from pychecker2 import ImportChecks +from pychecker2 import ClassChecks +from pychecker2 import ReachableChecks +from pychecker2 import ReturnChecks +from pychecker2 import ConditionalChecks +from pychecker2 import FormatStringChecks + +CACHE_FILE = '/tmp/t' + +def print_warnings(f, out): + if not f.warnings: + return 0 + f.warnings.sort() + last_line = -1 + last_msg = None + for line, warning, args in f.warnings: + if warning.value: + msg = warning.message % args + if msg != last_msg or line != last_line: + print >>out, \ + '%s:%s %s' % (f.name, line or '[unknown line]', msg) + last_msg, last_line = msg, line + if last_msg: + print >>out + return 1 + +def create_checklist(options): + + checks = [ ParseChecks.ParseCheck(), + OpChecks.OpCheck(), + OpChecks.ExceptCheck(), + OpChecks.CompareCheck(), + ReachableChecks.ReachableCheck(), + ConditionalChecks.ConstantCheck(), + ClassChecks.ReprCheck(), + ImportChecks.ImportCheck(), + FormatStringChecks.FormatStringCheck(), + VariableChecks.ShadowCheck(), + VariableChecks.UnpackCheck(), + VariableChecks.UnusedCheck(), + VariableChecks.UnknownCheck(), + VariableChecks.SelfCheck(), + VariableChecks.UsedBeforeSetCheck(), + ReturnChecks.MixedReturnCheck(), + ClassChecks.AttributeCheck(), + ClassChecks.SpecialCheck(), + ClassChecks.InitCheck(), + ScopeChecks.RedefineCheck(), + ] + for checker in checks: + checker.get_warnings(options) + checker.get_options(options) + return CheckList(checks) + +def main(): + import cPickle + + options = Options.Options() + try: + checker = cPickle.load(open(CACHE_FILE, 'rb')) + except (EOFError, IOError): + checker = create_checklist(options) + + try: + files = options.process_options(sys.argv[1:]) + except Options.Error, detail: + print >> sys.stderr, "Error: %s" % detail + options.usage(sys.argv[0], sys.stderr) + return 1 + + for f in files: + checker.check_file(f) + if options.incremental and not options.profile: + print_warnings(f, sys.stdout) + + result = 0 + if not options.incremental and not options.profile: + files.sort() + for f in files: + result |= print_warnings(f, sys.stdout) + + if not result and options.verbose: + print >>sys.stdout, None + + fp = open(CACHE_FILE, 'wb') + cPickle.dump(checker, fp, 1) + fp.close() + + return result + +if __name__ == "__main__": + if '--profile' in sys.argv: + print 'profiling' + import hotshot.stats + import time + hs = hotshot.Profile('logfile.dat') + now = time.time() + hs.run('main()') + print 'total run time', time.time() - now + hs.close() + stats = hotshot.stats.load('logfile.dat') + stats.sort_stats('time', 'cum').print_stats(50) + else: + sys.exit(main()) --- /dev/null +++ pychecker-0.8.19/pychecker2/ImportChecks.py @@ -0,0 +1,93 @@ +from pychecker2.Check import Check +from pychecker2.Check import Warning +from pychecker2 import util + +from compiler import walk + +class ModuleReference: + def __init__(self, localname, remotename, module, nodes): + self.localname = localname + self.remotename = remotename + self.module = module + self.nodes = nodes + + def __getstate__(self): + return (self.localname, self.remotename, self.module.__name__, + self.nodes) + + def __setstate__(self, data): + (self.localname, self.remotename, module, self.nodes) = data + self.module = __import__(module, globals(), {}, ['']) + +class ImportCheck(Check): + ''' +Get 'from module import *' names hauled into the file and modules. +Figure out which names come from 'import name'. + ''' + + importError = Warning('Report/ignore imports that may fail', + 'Error trying to import %s: %s') + duplicateImport = Warning('Report/ignore duplicate imports', + 'Import of "%s" is duplicate%s') + shadowImport = Warning('Report imports which shadow names from ' + 'other imports', + 'Import of "%s" duplicates import from ' + 'module %s at %d') + + def check(self, file, checker): + def try_import(name, node): + try: + return __import__(name, globals(), {}, ['']) + except ImportError, detail: + file.warning(node, ImportCheck.importError, name, str(detail)) + except Exception, detail: + file.warning(node, ImportCheck.importError, name, str(detail)) + return None + + def add_import(node, local, remote, module): + scopes = util.enclosing_scopes(file.scopes, node) + for scope in scopes: + try: + ref = scope.imports[local] + if not util.try_if_exclusive(ref.nodes, node): + if ref.module == module: + if scope == scopes[0]: + extra = " in current scope" + else: + extra = " of import in parent scope %s" % scope + file.warning(node, ImportCheck.duplicateImport, + local, extra) + else: + file.warning(node, ImportCheck.shadowImport, + local, + ref.module.__name__, + ref.nodes.lineno) + except KeyError: + pass + scopes[0].imports[local] = ModuleReference(local, remote, + module, node) + checker.check_module(module) + + class FromImportVisitor: + + def visitFrom(self, node): + m = try_import(node.modname, node) + if m: + for module_name, local_name in node.names: + if module_name == '*': + for name in dir(m): + if not name.startswith('_'): + add_import(node, name, name, m) + else: + add_import(node, local_name or module_name, + module_name, m) + + def visitImport(self, node): + for module, name in node.names: + m = try_import(module, node) + if m: + add_import(node, name or module, None, m) + + + if file.root_scope: + walk(file.root_scope.node, FromImportVisitor()) --- /dev/null +++ pychecker-0.8.19/pychecker2/File.py @@ -0,0 +1,39 @@ +from pychecker2.util import parents + +from compiler import ast + +class File: + def __init__(self, name): + self.name = name + self.parseTree = None + self.scopes = {} + self.root_scope = None + self.warnings = [] + + def __cmp__(self, other): + return cmp(self.name, other.name) + + def warning(self, line, warn, *args): + lineno = getattr(line, 'lineno', line) + if not lineno and hasattr(line, 'parent'): + for p in parents(line): + if p.lineno: + lineno = p.lineno + break + self.warnings.append( (lineno, warn, args) ) + + def scope_filter(self, type): + return [x for x in self.scopes.iteritems() if isinstance(x[0], type)] + + def function_scopes(self): + return self.scope_filter(ast.Function) + + def class_scopes(self): + return self.scope_filter(ast.Class) + + def not_class_scopes(self): + result = [] + for n, s in self.scopes.iteritems(): + if not isinstance(n, ast.Class): + result.append( (n, s) ) + return result --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/parseerror.py @@ -0,0 +1,24 @@ +from pychecker2 import TestSupport +from pychecker2 import ParseChecks +from pychecker2 import VariableChecks +from pychecker2.File import File + +class UnknownTestCase(TestSupport.WarningTester): + def testParseError(self): + self.warning('===\n', 1, ParseChecks.ParseCheck.syntaxErrors, + 'could not parse string') + f = File('no-such-file') + self.checklist.check_file(f) + self.warning_file(f, 0, ParseChecks.ParseCheck.syntaxErrors, + "No such file or directory") + + self.warning('if __name__=="__main__":\n' + ' _x = 1\n', + 2, VariableChecks.UnusedCheck.unused, '_x') + self.argv = ['--no-main'] + self.silent('NoMoreGood = 1\n' + 'assert NoMoreGood\n') + self.silent('if __name__=="__main__":\n' + ' _x = 1\n') + self.silent('if "__main__"==__name__:\n' + ' _x = 1\n') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/import.py @@ -0,0 +1,33 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ImportChecks + +class ImportTestCase(WarningTester): + def testImportChecks(self): + self.silent('import sys; print sys.argv') + self.silent('import pychecker2; print pychecker2') + self.silent('import pychecker2.utest; print pychecker2.utest') + + def testImportChecks(self): + self.warning('import sys\n' + 'print sys.argv\n' + 'import sys\n', + 3, ImportChecks.ImportCheck.duplicateImport, + 'sys', ' in current scope') + self.warning('from sys import *\n' + 'def f():\n' + ' def g():\n' + ' from sys import argv\n' + ' return argv\n' + ' return g() + g()\n' + 'print argv\n', + 4, ImportChecks.ImportCheck.duplicateImport, 'argv', + ' of import in parent scope ') + self.warning('import no_such_module\n', + 1, ImportChecks.ImportCheck.importError, 'no_such_module', + 'No module named no_such_module') + self.warning('from pychecker2.utest.data import *\n' + 'import exceptions\n' + 'print exceptions\n', + 2, ImportChecks.ImportCheck.shadowImport, + 'exceptions', 'pychecker2.utest.data', 1) + --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/conditional.py @@ -0,0 +1,27 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ConditionalChecks + +class ConditionalTestCase(WarningTester): + def testConstants(self): + w = ConditionalChecks.ConstantCheck.constantInConditional + + self.silent('a, b = 1, 2\n' + 'if a < b:\n' + ' print a\n') + self.warning('a = 1\n' + 'if a or 1:\n' + ' print a\n', 2, w, '1') + self.warning('a = 1\n' + 'if not 1:\n' + ' print a\n', 2, w, '1') + self.silent('a, b = 1, 2\n' + 'if a < 1 + 7:\n' + ' print a\n') + self.warning('result = [x for x in [1, 2, 3] if x or 1]\n', + 1, w, '1') + self.warning('result = [x for x in [1, 2, 3] if x or None]\n', + 1, w, 'None') + self.warning('x = 1\n' + 'while x or None:\n' + ' x = x + 1\n', + 2, w, 'None') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/class.py @@ -0,0 +1,232 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ClassChecks + +class ClassTestCase(WarningTester): + def testClassChecks(self): + self.silent('class A:\n' + ' def f(self):\n' + ' return 0\n' + 'class B(A):\n' + ' def g(self):\n' + ' return self.f\n') + def testSignature(self): + w = ClassChecks.AttributeCheck.signatureChanged + self.silent('class Base:\n' + ' def f(self): pass\n' + 'class Derived(Base):\n' + ' def f(self): pass\n') + self.warning('class Base:\n' + ' def f(self): pass\n' + 'class Derived(Base):\n' + ' def f(self, x): pass\n', + 4, w, 'f', 'Base') + self.silent('class Base:\n' + ' def f(self, x, y, *args): pass\n' + 'class Derived(Base):\n' + ' def f(self, x, *args): pass\n') + self.warning('class Base:\n' + ' def f(self, x, *args): pass\n' + 'class Derived(Base):\n' + ' def f(self, x, y, *args): pass\n', + 4, w, 'f', 'Base') + self.silent('class Base:\n' + ' def __private(self, x, y): pass\n' + 'class Derived(Base):\n' + ' def __private(self, x): pass\n') + self.warning('class Base:\n' + ' def __private(self, x, y): pass\n' + 'class Derived(Base):\n' + ' def _Base__private(self, x): pass\n', + 4, w, '__private', 'Base') + + def testUnknownAttribute(self): + w = ClassChecks.AttributeCheck.unknownAttribute + self.warning('class C:\n' + ' def f(self): return self.x\n', 2, w, 'C', 'x') + self.silent('class C:\n' + ' def f(self): return self.x\n' + ' def __init__(self, v): self.x = v\n') + self.silent('class D:\n' + ' def __init__(self): self.x = 1\n' + 'class C(D):\n' + ' def f(self): return self.x\n') + self.silent('from pychecker2.utest.data import *\n' + 'class C(Data):\n' + ' def get_value2(self):\n' + ' return self.get_value()\n' + '\n') + imp = '\n\nimport' + frm = '\n\nfrom' + import_abuse = [ + (imp, 'pychecker2.utest.data', 'pychecker2.utest.data.Data'), + (imp, 'pychecker2.utest.data as F', 'F.Data'), + (frm, 'pychecker2.utest import data', 'data.Data'), + (frm, 'pychecker2.utest import data as F', 'F.Data'), + (frm, 'pychecker2.utest.data import Data', 'Data'), + (frm, 'pychecker2.utest.data import Data as F', 'F'), + (frm, 'pychecker2.utest.data import *', 'Data'), + ('class A:\n class B:\n import pychecker2.utest.data', + '', + 'A.B.pychecker2.utest.data.Data'), + ('class A:\n' + ' class B:\n' + ' from pychecker2.utest import data as F', + '', + 'A.B.F.Data') + ] + for fmt in import_abuse: + self.silent('%s %s\n' + 'class C(%s):\n' + ' def f(self): return self.value\n' % fmt) + self.silent('%s %s\n' + 'def g(v):\n' + ' class C(%s):\n' + ' def f(self): return self.value\n' + ' return C(v)\n' % fmt) + self.warning('%s %s\n' + 'class C(%s):\n' + ' def f(self): self.get_value = 1\n' % fmt, + 5, ClassChecks.AttributeCheck.methodRedefined, + 'get_value', 'C') + + self.warning('%s %s\n' + 'def g(v):\n' + ' class C(%s):\n' + ' def f(self): self.get_value = 1\n' + ' return C(v)\n' % fmt, + 6, ClassChecks.AttributeCheck.methodRedefined, + 'get_value', 'C') + + self.warning('%s %s\n' + 'class C(%s):\n' + ' def get_value(self, x): pass\n' % fmt, + 5, ClassChecks.AttributeCheck.signatureChanged, + 'get_value', 'Data') + + def testSpecial(self): + for fmt in [('__del__', 'self, args', 1), + ('__cmp__', 'self', 2), + ]: + self.warning('class C:\n' + ' def %s(%s):\n' + ' pass\n' % fmt[0:2], + 2, ClassChecks.SpecialCheck.specialMethod, + fmt[0], fmt[2], fmt[2] > 1 and "s" or "") + for fmt in [('__del__', 'self'), + ('__ge__', 'self, a, b = None, c = None'), + ]: + self.silent('class C:\n' + ' def %s(%s):\n' + ' pass\n' % fmt) + self.warning('class C:\n' + ' def __not_special__(self):\n' + ' pass\n', + 2, ClassChecks.SpecialCheck.notSpecial, + '__not_special__') + + def testUncheckableAttribute(self): + # inherit from local variable + self.silent('def f(klass):\n' + ' class C(klass):\n' + ' def __init__(self, x):\n' + ' self.foo = x\n' + ' def g(self): return self.foo\n' + ' return C(1)\n') + # inherit from an expression + self.silent('class A:\n' + ' def __add__(self, unused):\n' + ' return A\n' + 'class B(A): pass\n' + 'class C(A() + B()): pass\n') + # inherit from something not in a source module + self.warning('import exceptions\n' + 'class C(exceptions):\n' + ' def f(self):\n' + ' return self.value\n', + 4, ClassChecks.AttributeCheck.unknownAttribute, + 'C', 'value') + self.warning('import pychecker2.utest.data\n' + 'class C(pychecker2.utest.data.exceptions.AssertionError):\n' + ' def f(self):\n' + ' return self.value\n', + 4, ClassChecks.AttributeCheck.unknownAttribute, + 'C', 'value') + self.warning('from pychecker2.utest.data import Data as F\n' + 'class C(F.DataError):\n' + ' def f(self):\n' + ' return self.value\n', + 4, ClassChecks.AttributeCheck.unknownAttribute, + 'C', 'value') + self.silent('def f():\n' + ' class Foo(None.__class__): pass\n' + ' return Foo()\n') + + def testUnused(self): + self.warning('class C:\n' + ' def __init__(self):\n' + ' self.__x = 1\n', + 3, ClassChecks.AttributeCheck.unusedAttribute, '__x', 'C') + self.warning('class C:\n' + ' def __init__(self):\n' + ' class D:\n' + ' def __init__(self): self.__x = 1\n' + ' def f(self):\n' + ' return self.__x\n' + ' self.__x = D()\n', + 7, ClassChecks.AttributeCheck.unusedAttribute, '__x', 'C') + self.silent('class C:\n' + ' def __init__(self):\n' + ' self.x = 1\n') + + def testInit(self): + w = ClassChecks.InitCheck.initReturnsValue + self.warning('class C:\n' + ' def __init__(self):\n' + ' return 1\n', 3, w) + self.warning('class C:\n' + ' def __init__(self):\n' + ' def f(x):\n' + ' return f(x - 1)\n' + ' return f(1)\n', 5, w) + + w = ClassChecks.AttributeCheck.attributeInitialized + self.silent('class C:\n' + ' def f(self):\n' + ' self.value = 1\n' + ' def __init__(self):\n' + ' self.value = None\n') + self.warning('class C:\n' + ' def __init__(self): pass\n' + ' def f(self):\n' + ' self.value = 1', + 4, w, 'value') + + def testRepr(self): + w = ClassChecks.ReprCheck.backquoteSelf + self.silent('class C:\n' + ' def __str__(self):\n' + ' return "C" + `self`\n') + self.warning('class C:\n' + ' def __repr__(self):\n' + ' return "C" + `self`\n', 3, w) + + def testMethodRedefined(self): + w = ClassChecks.AttributeCheck.methodRedefined + + self.warning('class C:\n' + ' def f(self):\n' + ' self.f = lambda x: x\n', + 3, w, 'f', 'C') + self.warning('class B:\n' + ' def g(self): pass\n' + 'class C(B):\n' + ' def f(self):\n' + ' self.g = lambda x: x\n', + 5, w, 'g', 'C') + self.warning('from pychecker2.utest.data import Data\n' + 'class C(Data):\n' + ' def f(self):\n' + ' self.get_value = 1\n', + 4, w, 'get_value','C') + + --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/unknown.py @@ -0,0 +1,27 @@ +from pychecker2 import TestSupport +from pychecker2 import VariableChecks + +class UnknownTestCase(TestSupport.WarningTester): + def testUnknown(self): + self.warning('def f(): print a\n', + 1, VariableChecks.UnknownCheck.unknown, 'a') + self.silent('def f():\n' + ' a = 1\n' + ' def g():\n' + ' print a\n' + ' print g()\n') + self.warning('def f():\n' + ' def g():\n' + ' print a\n' + ' print g()\n', + 3, VariableChecks.UnknownCheck.unknown, 'a') + self.silent('from sys import *\n' + 'def f():\n' + ' print argv\n') + self.silent('import sys\n' + 'def f():\n' + ' def g():\n' + ' print g, sys\n') + self.silent('def f():\n' + ' for a, b in [(1,2)]:\n' + ' print a, b\n') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/self.py @@ -0,0 +1,45 @@ +from pychecker2 import TestSupport +from pychecker2 import VariableChecks + +class SelfTestCase(TestSupport.WarningTester): + def testSelf(self): + self.warning('class C:\n' + ' def f(x): return x\n', + 2, VariableChecks.SelfCheck.selfName, + 'f', 'x', "['self', 'this', 's']") + + def testSelfNames(self): + self.silent('class C:\n' + ' def f(self): return self\n') + self.argv = ["--selfNames=['x']"] + self.warning('class C:\n' + ' def f(self): return self\n', + 2, VariableChecks.SelfCheck.selfName, + 'f', 'self', "['x']") + + def testSelfDefault(self): + w = VariableChecks.SelfCheck.selfDefault + self.warning('class C:\n' + ' def f(s=None): return s\n', 2, w, 'f', 's') + self.warning('class C:\n' + ' def f(s=None, **kw): return s, kw\n', 2, w, 'f', 's') + self.warning('class C:\n' + ' def f(s=None, *args): return s, args\n', + 2, w, 'f', 's') + self.warning('class C:\n' + ' def f(s=None, *args, **kw): return s, args, kw\n', + 2, w, 'f', 's') + + def testFunctionSelf(self): + w = VariableChecks.SelfCheck.functionSelf + self.warning('def f(a, self, b): return a + self + b\n', + 1, w, 'f', 'self') + self.argv = ["--selfSuspicious=['a']"] + self.warning('def f(a, self, b): return a + self + b\n', + 1, w, 'f', 'a') + + def testMissingSelf(self): + w = VariableChecks.SelfCheck.missingSelf + self.warning('class C:\n' + ' def f(): pass\n', 2, w, 'f') + --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/scopes.py @@ -0,0 +1,47 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ScopeChecks + +class RedefinedTestCase(WarningTester): + def testScopes(self): + w = ScopeChecks.RedefineCheck.redefinedScope + self.warning('def f(): pass\n' + 'def f(): pass\n', + 1, w, 'f', 2) + self.warning('class C:\n' + ' def g(self): pass\n' + ' def g(self): pass\n', + 2, w, 'g', 3) + self.silent('def s(): pass\n' + 'def f(): pass\n') + self.silent('import sys\n' + 'if sys.argv:\n' + ' def f(): return 1\n' + 'else:\n' + ' def f(): return 0\n') + self.warning('import sys\n' + 'if sys.argv:\n' + ' def f(): return 1\n' + ' def f(): return 0\n', + 3, w, 'f', 4) + self.warning('try:\n' + ' def f(): return 1\n' + 'except Exception:\n' + ' pass\n' + 'else:\n' + ' def f(): return 0\n', + 2, w, 'f', 6) + self.warning('try:\n' + ' def f(): return 1\n' + ' def f(): return 0\n' + 'except Exception:\n' + ' pass\n' + 'else:\n' + ' pass\n', + 2, w, 'f', 3) + + self.silent('try:\n' + ' def f(): return 1\n' + 'except Exception:\n' + ' def f(): return 0\n' + 'else:\n' + ' pass\n') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/shadow.py @@ -0,0 +1,21 @@ +from pychecker2 import TestSupport +from pychecker2 import VariableChecks + +class ShadowTestCase(TestSupport.WarningTester): + def testShadow(self): + "Test variable shadowing" + self.warning('a = 1\n' + 'def f(x):\n' + ' a = x\n' + ' return x + a\n', + 3, VariableChecks.ShadowCheck.shadowIdentifier, + 'a', '') + self.warning('file = None\n', + 1, VariableChecks.ShadowCheck.shadowBuiltins, 'file') + + w = VariableChecks.ShadowCheck.defineNone + self.silent('none, x = 1, 2') + self.warning('None = None', 1, w) + self.warning('def None(x, y): pass', 1, w) + self.warning('None, x = 1, 2', 1, w) + self.warning('class None: pass', 1, w) --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/ops.py @@ -0,0 +1,43 @@ +from pychecker2 import TestSupport +from pychecker2 import OpChecks + +class OpTests(TestSupport.WarningTester): + def testOperator(self): + for op in ['--', '++']: + self.warning('def f(x):\n' + ' return %sx' % op, + 2, OpChecks.OpCheck.operator, op) + + def testOperatorPlus(self): + self.warning('def f(x):\n' + ' return +x', 2, OpChecks.OpCheck.operatorPlus) + + def testEqualNone(self): + self.silent('def f(x):\n' + ' return 1 <= x <= None\n') + self.warning('def f(x):\n' + ' return x == None\n', 2, OpChecks.CompareCheck.useIs) + self.warning('def f(x):\n' + ' return 1 == x == None\n', 2, OpChecks.CompareCheck.useIs) + self.warning('def f(x):\n' + ' return None == x == 1\n', 2, OpChecks.CompareCheck.useIs) + self.warning('def f(x):\n' + ' return None == x\n', 2, OpChecks.CompareCheck.useIs) + + def testExcept(self): + self.warning('try:\n' + ' pass\n' + 'except:\n' + ' pass\n', 4, OpChecks.ExceptCheck.emptyExcept) + self.warning('try:\n' + ' pass\n' + 'except AssertionError:\n'\ + ' pass\n' + 'except:\n' + ' pass\n', 6, OpChecks.ExceptCheck.emptyExcept) + self.warning('try:\n' + ' pass\n' + 'except:\n' + ' pass\n' + 'except AssertionError:\n'\ + ' pass\n', 4, OpChecks.ExceptCheck.emptyExcept) --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/__init__.py @@ -0,0 +1 @@ +"" --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/data.py @@ -0,0 +1,8 @@ +import exceptions + +class Data: + class DataError(exceptions.ValueError): pass + def __init__(self, value): + self.value = value + def get_value(self): + return self.value --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/usage.py @@ -0,0 +1,7 @@ +from pychecker2.TestSupport import WarningTester +from StringIO import StringIO + +class UsageTestCase(WarningTester): + def testUsage(self): + self.options.usage(['-?'], StringIO()) + --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/unused.py @@ -0,0 +1,96 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import VariableChecks + +class UnusedTestCase(WarningTester): + def testUnusedBasic(self): + self.warning('def f(i, j): return i * 2\n', + 1, VariableChecks.UnusedCheck.unused, 'j') + self.warning('def _unused(): pass\n', + 1, VariableChecks.UnusedCheck.unused, '_unused') + self.silent('def f(x):\n' + ' def g():\n' + ' x.y.z, = 1\n' + ' g()\n') + + def testUnusedAbstract(self): + self.silent('def f(i): assert 0\n') + self.silent('def f(i): assert None\n') + self.silent('def f(i): return\n') + self.silent('def f(i): return 7\n') + self.silent('def f(i): pass\n') + self.silent('def f(i): raise NotImplementedError\n') + + def testUnusedScopeNotSelf(self): + self.silent('class A:\n' + ' def f(self, j): return j * 2\n') + self.argv = ['--reportUnusedSelf'] + self.warning('class A:\n' + ' def f(self, j): return j * 2\n', + 2, VariableChecks.UnusedCheck.unused, 'self') + + def testUnusedScope(self): + self.warning('class A:\n' + ' def f(self, j): return self\n', 2, + VariableChecks.UnusedCheck.unused, 'j') + self.silent('def f(a, b):\n' + ' def g(x):\n' + ' return x * a\n' + ' return g(b)\n') + + def testUnusedIgnore(self): + self.warning('def f(a, xyzzySilly): return a\n', + 1, VariableChecks.UnusedCheck.unused, 'xyzzySilly') + self.argv = ['--unusedPrefixes=["xyzzy"]'] + self.silent('def f(a, xyzzySilly): return a\n') + + + def testGlobal(self): + self.silent('x = 1\ndef f(x=x): return 7\n') + self.silent('def f(x):\n' + ' global _y\n' + ' _y = x\n' + 'def g(x): return x + _y\n') + + def testUnpack(self): + w = VariableChecks.UnusedCheck.unused + self.silent('_x, _y = 1, 2\n') + self.silent('def f(a, (b, c)): print a, b\n') + self.silent('def f(a, (b, (c, d))): print a, b\n') + + self.argv = ['--no-unpackedUsed'] + self.warning('_x, _y = 1, 2\n' + 'print _x\n', 1, w, '_y') + self.warning('def f(a, (b, c)): print a, b\n', 1, w, 'c') + self.silent('def f(a):\n' + ' "this is an empty function"\n') + + def testUsedBeforeSet(self): + w = VariableChecks.UsedBeforeSetCheck.usedBeforeDefined + self.warning('G1 = 1\n' + 'def f(L1, (L2, L3)):\n' + ' x = 1\n' + ' if G1:\n' + ' y = 2\n' + ' if G1:\n' + ' z = 1\n' + ' y = 2\n' + ' else:\n' + ' z = 2\n' + ' return L1, L2, L3, x, y, z\n', + 11, w, 'y') + self.silent('def f():\n' + ' import sys\n' + ' return sys.argv\n') + self.silent('def f():\n' + ' from sys import argv\n' + ' return argv\n') + self.silent('def f():\n' + ' from sys import *\n' + ' return argv\n') + self.silent('def f():\n' + ' return [(a, b) for a, b in [(1,2)]]\n') + self.silent('def f():\n' + ' r = [(a, b) for a, b in [(1,2)]]\n' + ' return r, a, b\n') + self.silent('import pychecker2.utest\n' + 'print pychecker2.utest.data.exceptions.Warning()') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/reachable.py @@ -0,0 +1,73 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ReachableChecks + +class ReachableTestCase(WarningTester): + def testUnreachable(self): + w = ReachableChecks.ReachableCheck.unreachable + self.warning('v1, v2 = 0, 0\n' + 'def f():\n' + ' if v1:\n' + ' return v2\n' + ' elif v2:\n' + ' return 1\n' + ' else:\n' + ' return 0\n' + ' return 1\n', 9, w) + self.warning('v1, v2 = 0, 0\n' + 'def f():\n' + ' if v1:\n' + ' raise AssertionError("assertion")\n' + ' elif v2:\n' + ' assert 0, "Another error"\n' + ' else:\n' + ' return 0\n' + ' return f()\n', 9, w) + self.silent('def f(x):\n' + ' while x:\n' + ' pass\n') + self.silent('def f(x):\n' + ' for i in x:\n' + ' assert i\n') + self.silent('def f(x):\n' + ' if x:\n' + ' return 0\n' + ' return 0\n') + self.warning('def f(x):\n' + ' try:\n' + ' x = 1 / x\n' + ' return x\n' + ' except Exception:\n' + ' return 0\n' + ' else:\n' + ' x = 7\n' + ' return x\n', 8, w) + + self.silent('def f(v1, v2):\n' + ' if v1:\n' + ' return v2\n' + ' elif v2:\n' + ' v1 = v2\n' + ' else:\n' + ' assert 0, "Another error"\n' + ' return f()\n') + + self.silent('def f(v1, v2):\n' + ' if v1:\n' + ' return v2\n' + ' elif v2:\n' + ' v1 = v2\n' + ' else:\n' + ' assert 0, "Another error"\n' + ' return 0\n') + + self.silent('def f(x):\n' + ' try:\n' + ' return 1.0 / x\n' + ' except ZeroDivisionError:\n' + ' raise\n') + + def testImplicitReturn(self): + w = ReachableChecks.ReachableCheck.implicitReturn + self.warning('def f(v1, v2):\n' + ' if v1:\n' + ' return v2\n', 2, w, 'f') --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/returns.py @@ -0,0 +1,21 @@ +from pychecker2.TestSupport import WarningTester +from pychecker2 import ReturnChecks + +class ReturnTestCase(WarningTester): + def testReturnChecks(self): + w = ReturnChecks.MixedReturnCheck.mixedReturns + self.silent('def f(): return\n') + self.silent('def f(): return 1\n') + self.silent('def f(x):\n' + ' if x:\n' + ' return 0\n' + ' return 1\n') + self.warning('def f(x):\n' + ' if x:\n' + ' return\n' + ' return 1\n', 3, w, 'f') + self.silent('def f(x):\n' + ' def g():\n' + ' return\n' + ' return x + g()\n') + --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/format.py @@ -0,0 +1,78 @@ +from pychecker2 import TestSupport +from pychecker2 import FormatStringChecks + +class FormatTestCase(TestSupport.WarningTester): + + def testGoodFormats(self): + self.silent('def f(x):\n' + ' return "%s" % x\n') + self.silent('def f(x):\n' + " return ('%s' + '%s') % (x, x)\n") + self.silent("def f(x):\n" + " return (('%s' + '%s') * 8) % ((x,) * 16)\n") + self.silent("def f(x):\n" + " y = 2\n" + " return '%(x)f %(y)s' % locals()\n") + self.silent("y = 1\n" + "def f():\n" + " return '%(y)s' % globals()\n") + self.silent("def f():\n" + " return '%*.s %*.*s %*f' % locals()\n") + self.silent("def f():\n" + " return '%s %%' % ('',)\n") + self.silent("def f(t):\n" + " return '%s %f' % t\n") + self.silent("def f(t):\n" + " return ('%s %f' + t) % (1, 2)\n") + self.silent("def f(t):\n" + " return '%s' % `t`\n") + self.silent("def f(t):\n" + " return '%s' * ((7 - 1) / 2) % (t,t,t)\n") + + def testBadFormats(self): + w = FormatStringChecks.FormatStringCheck.badFormat + self.warning("def f():\n" + " return '%' % locals()\n", 2, w, 0, '%') + self.warning("def f():\n" + " return '%z a kookie format, yah' % locals()\n", + 2, w, 0, '%z a kooki...') + self.warning("def f():\n" + " return '%(foo)*.*s' % {'foo': 'bar'}\n", + 2, w, 0, '%(foo)*.*s') + + def testMixed(self): + w = FormatStringChecks.FormatStringCheck.mixedFormat + self.warning("def f():\n" + " return '%(mi)x %up' % locals()\n", 2, w, '(mi)') + self.warning("def f():\n" + " return '%up %(mi)x' % (1, 2)\n", 2, w, '(mi)') + + def testFormatCount(self): + w = FormatStringChecks.FormatStringCheck.formatCount + self.warning("def f():\n" + " return '%s %d %f' % ('', 2)\n", + 2, w, 2, 3) + + def testUselessModifier(self): + w = FormatStringChecks.FormatStringCheck.uselessModifier + self.warning("def f(t):\n" + " return '%s %lf' % (t, t)\n", + 2, w, 'l') + + def testFormatConstants(self): + w = FormatStringChecks.FormatStringCheck.badConstant + self.warning("def f():\n" + " return ('%s' * 6) % ((1, 2) + 3 * 7)\n", + 2, w, 'can only concatenate tuple (not "int") to tuple') + self.warning("def f():\n" + " return ('%s' + 6) % ((1, 2) * 3)\n", + 2, w, "cannot concatenate 'str' and 'int' objects") + + def testUnknownName(self): + w = FormatStringChecks.FormatStringCheck.unknownFormatName + self.warning("def f():\n" + " return '%(unknown)s' % globals()\n", + 2, w, "unknown", "globals") + self.warning("def f():\n" + " return '%(unknown)s' % locals()\n", + 2, w, "unknown", "locals") --- /dev/null +++ pychecker-0.8.19/pychecker2/utest/warnings.py @@ -0,0 +1,23 @@ +from pychecker2 import TestSupport +from pychecker2 import OpChecks +from pychecker2 import main + +from StringIO import StringIO + +class OpTests(TestSupport.WarningTester): + + def _get_warnings(self): + out = StringIO() + f = self.check_file('def f(x):\n' + ' return +x\n') + assert len(f.warnings) == 1 + line, warning, args = f.warnings[0] + main.print_warnings(f, out) + return out.getvalue() + + def testWarningSuppression(self): + # check cmd-line warning suppression + assert self._get_warnings() != '' + self.argv = ['--no-operatorPlus'] + assert self._get_warnings() == '' + --- /dev/null +++ pychecker-0.8.19/pychecker2/scripts/pychecker2.sh @@ -0,0 +1,6 @@ +#! /bin/sh +NAME=$0 # this script +NAME=`dirname $NAME` # trim scripts +NAME=$NAME/../.. +export PYTHONPATH=$PYTHONPATH:$NAME +exec python2.2 $NAME/pychecker2/main.py $@ --- /dev/null +++ pychecker-0.8.19/pychecker2/scripts/lib.sh @@ -0,0 +1,2 @@ +#! /bin/sh +scripts/pychecker2.sh --incremental --no-importError --no-unused --no-shadowIdentifier --no-shadowImport --no-emptyExcept --no-attributeInitialized /usr/local/lib/python2.2/*.py --- /dev/null +++ pychecker-0.8.19/pychecker2/scripts/clean.sh @@ -0,0 +1,5 @@ +#! /bin/sh +for i in `find . -type d -print` +do + /bin/rm -f *.pyc *.pyo *~ +done --- /dev/null +++ pychecker-0.8.19/pychecker2/scripts/check.sh @@ -0,0 +1,4 @@ +#! /bin/sh +PYTHONPATH=$PYTHONPATH:.. pychecker --stdlib *.py +echo ============================================================== +scripts/pychecker2.sh $* *.py --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/badparse.py @@ -0,0 +1 @@ +=== --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/import.py @@ -0,0 +1,19 @@ +from sys import path as foo, argv as bar# bar not used +import getopt # getopt not used +import os.path as nifty # nifty not used +from os.path import * + +def f(v): + from os.path import join # duplicate import + v.append(join(foo)) # join from os.path + v.append(__all__) # __all__ is unknown + +x = 7 +if x == 100: + from xYzZy import * # not found + x = z + +not_used = 13 +import getopt # duplicate import +from string import * # shadow 'join' + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/class.py @@ -0,0 +1,152 @@ +import compiler +import compiler as one +import compiler.ast +import compiler.ast as two +from compiler import ast +from compiler import ast as three +from compiler.ast import Const +from compiler.ast import Const as four + +func = lambda x: x + +class D: + class B(compiler.ast.Const): + inherited2 = 1 + def x(self): + self.inherited1 = 1 + +class A(D.B): + def __init__(self): + self.x = 1 # define x on A + self.w.q = 1 + + def f(s, self): # unusual self + print self + s.self = 1 + s = 7 + + def x(): # no self, redefine x on object + pass + + def y(self): + self.a, self.b = (1, 2) # define a, b + + def _z(self): + print self._z # method + print self.x # assigned + print self.a # unpacked + print self.w # unknown + print self.inherited1 # known from B + print self.inherited2 # known from B + print self.value # from compiler.ast.Const, fails + print self.goofy # defined in class scope + + goofy = x + +class E(one.ast.Const): + def f(self): + print self.value + +class F(two.Const): + def f(self): + print self.value + +class H(three.Const): + def f(self): + print self.value + +class I(four): + def f(self): + print self.value + +class J(ast.Const): + def f(self): + print self.value + +class K(Const): + def f(self): + print self.value + +# +# Various abusive imports, all under a non-global scope +# + +def z(arg): + from xml.dom import minidom as md + + class L(md.Node): + def f(self): + print arg, self.childNodes + print L() + +def zz(arg): + from xml import dom as d + + class L(d.minidom.Node): + def f(self): + print arg, self.childNodes # should fail + print L() + +def zzz(arg): + from xml.dom.minidom import Node as X + + class L(X): + def f(self): + print arg, self.childNodes + print L() + +def zzzz(arg): + from tests import nested + + class L(nested.N1.N2): + def f(self): + print self.x + print L(), arg + +class Base: + def f(self, x): pass +class Derived(Base): + def f(self): pass + +class Node(compiler.ast.Node): + def getChildren(self, x): + return x + +class Node2(compiler.ast.Slice): + def __init__(self): + return self + +class BadSpecial: + + def __del__(self): + return 0 + + def __cmp__(self, x): + return x + + def __len__(self): + return 0 + + def __le__(self): + return 0 + + def __gt__(self, a, b): + return 0 + + def __ge__(self, a, b = None, c = None): + return 0 + + def __setattr__(self, a = None): + return 0 + + def __not_special__(self): + return 0 + +class Z1: + class Z2: + from xml.dom import minidom as md + +class Z3(Z1.Z2.md.Node): + def f(self): + print self.childNodes + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/self.py @@ -0,0 +1,31 @@ + +class SelfTester: + + def f(self, a): + return a + +class SelfTester2: + + def f(x, a): + return a + +class SelfTester3: + + def f(x, a): + return x, a + +class SelfTester4: + + def f(self = 1): + return self + +class SelfTester5: + + def f(self = 1, *args, **kwargs): + return self, args, kwargs + +def f(self): + print self + +x = lambda self: self + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/shadow.py @@ -0,0 +1,59 @@ + +def f(a, b): + a = b + for a in range(10): + b += a + return b + +def f(a, b): + return a + b + +f = 3 + +max = 3 + +def g(a, b): + def f(c, d): + a = c + b = d + max + return f(c, d) + +class C: + f = lambda a, b: a + b + def f(self, b): + pass + +class D: + CONSTANT = 1 + def h(self, arg): + CONSTANT = D.CONSTANT + arg.append(CONSTANT) + +def xyzzy(a, max=max, *args, **kw): + print a, args, kw + return max + +if __name__ == '__main__': + a = 2 +if '__main__' == __name__: + a = 2 + +if x: + def f1(): + print x +else: + def f1(): + print x + +try: + def f2(): + print x +except AttributeError: + def f2(): + print x +except: + def f2(): + print x +else: + def f2(): # should still warn + print x --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/unreachable.py @@ -0,0 +1,58 @@ +v1=0 + +def f1(): + if v1: + v2 = 2 + 3 * 4 / 7 << 3; + return v2 + elif v2: + a, b = 1, 2 + b, a = a, b + return 0 + else: + print 7 + return 1 + return 0 # unreachable + +def f2(): + if v1: + return 0 + return 0 + +def f3(): + if v1: + raise v1 + else: + raise v1 + print v1 # unreachable + +def f4(): + assert None + print v1 # unreachable + +def f5(): + assert 1 + print v1 + +def f6(): + assert 0 + print v1 # unreachable + + +def f7(): + global v1 + try: + assert None + except KeyError: + v1 = 7 + else: + raise v1 # unreachable + return 0 + +def f8(): + try: + print v1() + except KeyError: + return 7 + else: + raise v1 + return 0 # unreachable --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/op.py @@ -0,0 +1,24 @@ +def f(a): + return ++a + +def g(a): + return +a + +def g(a): + return --a + +def foo(): + if 1 == None: + print "whoa!" + else: + print "whew!" + + if None == 1: + print "whoa!" + else: + print "whew!" + +def bar(): + a = b = 0 + if 'a' <= b >= 'c': + print "" --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/unused.py @@ -0,0 +1,31 @@ + +def f(a): + return 1 + +def g(): + class Test: + def q(self): + class TestInner: + def p(self, a): + return a + self.foo = TestInner() + + +x, y = 1, 2 +class Object: pass +x = Object() +x.y, x.z = 1, 2 + +def h(a, b, c): + assert 0, "should not be called" + +[x1, y1, z1] = [1, 2, 3] +[x1, y1, z1] = [y1, z1, x1] + +def xyzzy(): + global x + global y + y = 1 + +def XyZZy(a, (b, (c, d)), e): + return a + e --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/global.py @@ -0,0 +1,14 @@ + +if __name__ == "__main__": + x = y + +debug = 1 +def _debug(msg): + if debug: + print msg + +def main(): + import sys + global debug + debug = '-d' in sys.argv + _debug('debug is %d' % debug) --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/except.py @@ -0,0 +1,11 @@ + +try: + pass +except AttributeError: + pass + +try: + pass +except: + pass + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/nested.py @@ -0,0 +1,8 @@ + +class N1: + class N2: + x = 1 + class N3: + pass + + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/unusedImport.py @@ -0,0 +1,4 @@ +import sys + +def f(x): + return f(x) --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/format.py @@ -0,0 +1,48 @@ + +def f1(x): + return '%s' % x + +def f2(x): + return ('%s' + '%s') % (x, x) + +def f3(x): + return (('%s' + '%s') * 8) % ((x,) * 16) + +def f4(): + return '%(x)f %(y)s' % locals() + +def f5(): + return '%' % locals() + +def f6(): + return '%z this, too is a kookie format, yah' % locals() + +def f7(): + return '%*.s %*.*s %*f' % locals() + +def f8(): + return '%(mi)x %(it)s %up' % locals() + +def f9(): + return '%s %d %f' % ('', 2) + +def f10(): + return '%s %%' % ('',) + +def f11(t): + return '%s %f' % t + +def f12(t): + return '%s %lf' % (t, t) + +def f13(t): + return ('%s %f' + t) % (1, 2) + +def f14(): + return '%up %(mi)x' % (1, 2) + +def f15(): + return ('%s' * 6) % ((1, 2) + 3 * 7) + +def f16(): + return '%(foo)*.*s' % {'foo': 'bar'} --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-redefinedScope @@ -0,0 +1,47 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-unused @@ -0,0 +1,36 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/reportUnusedSelf @@ -0,0 +1,55 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:4 Identifier (self) not used +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:9 Identifier (x) not used +tests/self.py:14 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope +tests/shadow.py:28 Identifier (self) not used +tests/shadow.py:32 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used +tests/unused.py:9 Identifier (self) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/normal @@ -0,0 +1,47 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-unknown @@ -0,0 +1,43 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-operatorPlus @@ -0,0 +1,48 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/shadowBuiltins @@ -0,0 +1,50 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:13 Identifier (max) shadows builtin +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-unpackedUsed @@ -0,0 +1,52 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used +tests/unused.py:30 Identifier (b) not used +tests/unused.py:30 Identifier (c) not used +tests/unused.py:30 Identifier (d) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/verbose @@ -0,0 +1,69 @@ +Checking file tests/badparse.py + +Checking file tests/class.py + +Checking file tests/global.py + +Checking file tests/import.py + +Checking file tests/op.py + +Checking file tests/self.py + +Checking file tests/shadow.py + +Checking file tests/unusedImport.py + +Checking file tests/unused.py + +Checking file tests/not_there.py + +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/incremental @@ -0,0 +1,49 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unusedImport.py:1 Identifier (sys) not used + +tests/unused.py:6 Identifier (Test) not used + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-selfName @@ -0,0 +1,48 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/options @@ -0,0 +1,33 @@ +Error: option -? not recognized +Usage: + ./../pychecker2/main.py [options] [--] file1.py file2.py ... +available options: + +Error: + --no-duplicateImport Report/ignore duplicate imports + --no-hasAttribute Report unknown object attributes in methods + --no-importError Report/ignore imports that may fail + --no-main Ignore module-level code protected by __name__ == "__main__" + --no-methodRedefined Report the redefinition of class methods + --no-missingSelf Report methods without "self" + --no-operator Check for (++) and (--) which are legal, but not useful + --no-operatorPlus Check for unary + + --no-redefinedScope Report redefined scopes + --reportUnusedSelf Ignore unused method "self" parameter + --no-selfName Report any methods whose first argument is not self + --selfNames Name of self parameter + ['self', 'this', 's'] + --shadowBuiltins Report names that shadow builtins + --no-shadowIdentifier Report names already defined in outer scopes + --no-shadowImport Report imports which shadow names from other imports + --no-syntaxErrors Report/ignore syntax errors + --no-unknown Report names that are not defined + --no-unpackedUsed Do not treat variables used in tuple assignment as used + --no-unused Report names not used + --unusedPrefixes Ignore unused identifiers that start with these values + ['unused', 'empty', 'dummy', '__pychecker__', '__all__', '__version__', 'ignored'] + +Miscellaneous: + --incremental print warnings as they are created + --profile print a profile of pychecker + --verbose turn on verbose messages --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-shadowIdentifier @@ -0,0 +1,42 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-syntaxErrors @@ -0,0 +1,45 @@ +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-operator @@ -0,0 +1,47 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:13 Error trying to import xYzZy: No module named xYzZy +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + --- /dev/null +++ pychecker-0.8.19/pychecker2/tests/expected/no-importError @@ -0,0 +1,48 @@ +tests/badparse.py:1 Unable to parse: could not parse string + +tests/class.py:20 Method x defined at line 28 in class A redefined +tests/class.py:21 Class A has no attribute w +tests/class.py:28 Method x is missing self parameter +tests/class.py:38 Class A has no attribute w + +tests/global.py:3 Unknown identifier: y + +tests/import.py:1 Identifier (bar) not used +tests/import.py:3 Identifier (nifty) not used +tests/import.py:7 Import of "join" is duplicate of import in parent scope +tests/import.py:9 Unknown identifier: __all__ +tests/import.py:14 Unknown identifier: z +tests/import.py:17 Identifier (getopt) not used +tests/import.py:17 Import of "getopt" is duplicate in current scope +tests/import.py:18 Import of "join" duplicates import from module posixpath at 4 +tests/import.py:18 Import of "split" duplicates import from module posixpath at 4 + +tests/not_there.py:[unknown line] Unable to parse: [Errno 2] No such file or directory: 'tests/not_there.py' + +tests/op.py:2 Operator (++) doesn't exist, statement has no effect +tests/op.py:4 Scope (g) is redefined at line 7 +tests/op.py:5 Operator (+) normally has no effect +tests/op.py:8 Operator (--) doesn't exist, statement has no effect + +tests/self.py:9 First argument to method f (x) is not in ['self', 'this', 's'] +tests/self.py:14 Identifier (a) not used + +tests/shadow.py:2 Scope (f) is redefined at line 8 +tests/shadow.py:4 Identifier (a) shadows definition in scope +tests/shadow.py:15 Identifier (a) not used +tests/shadow.py:15 Identifier (b) not used +tests/shadow.py:15 Identifier (a) shadows definition in scope +tests/shadow.py:16 Identifier (f) shadows definition in scope +tests/shadow.py:17 Identifier (a) not used +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:17 Identifier (a) shadows definition in scope +tests/shadow.py:18 Identifier (b) not used +tests/shadow.py:18 Identifier (b) shadows definition in scope +tests/shadow.py:19 Unknown identifier: c +tests/shadow.py:19 Unknown identifier: d +tests/shadow.py:22 Identifier (a) shadows definition in scope + +tests/unused.py:6 Identifier (Test) not used + +tests/unusedImport.py:1 Identifier (sys) not used + debian/patches/series0000664000000000000000000000024312143254543012036 0ustar fix-version.patch remove-shebang.patch tweak-setup-py.patch put-back-missing-files-from-cvs.patch spe-improvements.patch remove-bashisms.patch dist-packages.patch debian/pychecker.install0000664000000000000000000000007512143254543012542 0ustar lib/pychecker/* usr/share/pyshared bin/pychecker usr/bin debian/pychecker.manpages0000664000000000000000000000002312143254543012660 0ustar debian/pychecker.1 debian/pychecker.examples0000664000000000000000000000001212143254543012701 0ustar pycheckrc debian/pychecker.preinst0000664000000000000000000000035612143254543012562 0ustar #!/bin/sh set -e # Remove old files left behind by previous versions of package if [ -d /usr/lib/site-python/pychecker ]; then rm -f /usr/lib/site-python/pychecker/*.pyo rm -f /usr/lib/site-python/pychecker/*.pyc fi #DEBHELPER# debian/changelog0000664000000000000000000006043312143266210011045 0ustar pychecker (0.8.19-8) unstable; urgency=low * Accept and upload Jakub's changes for jessie. * Use canonical URIs for Vcs-* fields. [ Jakub Wilk ] -- Kenneth J. Pronovici Fri, 10 May 2013 21:35:18 +0000 pychecker (0.8.19-7) unstable; urgency=low * Convert debian/rules to debhelper7, overriding just a few standard targets. * Update debian/README.debian to use dh_python2 rather than python-support. * Modify debian/pychecker.dirs to properly use usr/share/pyshared. * Modify debian/pychecker.install to install debian/wrapper. * Update debian/copyright to list 2013 as the copyright date on my changes. -- Kenneth J. Pronovici Wed, 24 Apr 2013 16:38:40 +0000 pychecker (0.8.19-6) unstable; urgency=low * Bump standards version to 3.9.4.0; no packaging changes. * Make minor tweaks in debian/rules for consistency. - Add new .PHONY targets for all rules that don't create files - Change binary to depend on both binary-arch and binary-indep - Change binary-arch to depend on install, not build and install -- Kenneth J. Pronovici Mon, 31 Dec 2012 20:15:45 +0000 pychecker (0.8.19-5) unstable; urgency=low * Update to machine-readable debian/copyright file format, version 1.0. * Add year 2012 to list of covered years for debian/* copyright statement. * Add Sandro to copyright statement for debian/* files. * Bump standards version to 3.9.3.0; no packaging changes. * Move to debhelper (>= 9) and debian/compat=9, which is the new standard. -- Kenneth J. Pronovici Mon, 12 Mar 2012 12:06:33 -0500 pychecker (0.8.19-4) unstable; urgency=low * Support dist-packages in addition to site-packages (closes: #648426). - Apply dist-patckages.patch, supplied by Nigel Evans -- Kenneth J. Pronovici Fri, 11 Nov 2011 10:06:03 -0600 pychecker (0.8.19-3) unstable; urgency=low * Bump standards version to 3.9.2.0; no packaging changes. * Fix Lintian warning: debian-rules-missing-recommended-target - Restructure build, build-arch, build-indep targets in debian/rules * Transition to dh_python2, since python-support is deprecated for Wheezy. - Replace Build-Depends: python-support with python-all in debian/control - Replace debian/pyversion with X-Python-Version: >= 2.1 in debian/control - Replace call to 'dh_pysupport -d' with 'dh_python2' in debian/rules - Replace python-support with pyshared in debian/pychecker.install - Tweak comments in debian/wrapper to reflect dh_python2 paths -- Kenneth J. Pronovici Fri, 05 Aug 2011 15:19:34 -0500 pychecker (0.8.19-2) unstable; urgency=low * Transfer maintainership to Python Applications Packaging Team on alioth. - Update debian/control to change Maintainer: - Update debian/control to change Uploaders: - Update debian/control to add Vcs-Svn: and Vcs:Browser -- Kenneth J. Pronovici Wed, 26 Jan 2011 23:08:13 -0600 pychecker (0.8.19-1) unstable; urgency=low * New upstream release. - This code is now compatible with Python 2.7 (closes: #609438) * Bump Standards-Version to 3.9.1.0 (no packaging changes). * Rewrite debian/regression.sh to handle the new upstream unit tests. * Update debian/copyright to reference Thomas Vander Stichele. * Update debian/pychecker.1 manpage to update the package version. * Update debian/README.Debian to clarify the status of pychecker2. * Update debian/patches/remove-shebang.patch to match upstream code. * Add new patch fix-version.patch so pychecker reports the right version. * Add new patch remove-bashisms.patch so test_check.sh runs with dash. * Add new patch put-back-missing-files-from-cvs.patch. - This patch adds back a *huge* number of files that were mistakenly not included in the official upstream 0.8.19 tarball. These files will be included in the 0.8.20 release, using a new MANIFEST.in which I provided. However, for the time being upstream has asked me to deal with this problem by patching the Debian package. All of the extra files that I have included in my 0.8.19-1 release were pulled directly from upstream CVS using 'cvs co -r v0_8_19'. -- Kenneth J. Pronovici Sun, 23 Jan 2011 19:47:08 -0600 pychecker (0.8.18-7) unstable; urgency=low * Fix warnings from the Full Lintian Report in the PTS. - Properly escape "-" in debian/pychecker.1 -- Kenneth J. Pronovici Sat, 10 Jul 2010 21:12:45 -0500 pychecker (0.8.18-6) unstable; urgency=low * Add support for DEB_BUILD_OPTIONS=nocheck in debian/rules. -- Kenneth J. Pronovici Fri, 02 Jul 2010 21:19:08 -0500 pychecker (0.8.18-5) unstable; urgency=low * Tweak short description to better match official recommendations. * Bump standards version to 3.9.0.0. * Add Homepage: tag in debian/control. * Convert debian/copyright to new DEP-5 machine-readable format. * Convert to source format "3.0 (quilt)" - Add new file debian/source/format - Add new patch debian/patches/tweak-setup-py.patch - Add new patch debian/patches/remove-shebang.patch - Add new patch debian/patches/spe-improvements.patch - Move Debian-specific tests and results to the debian/ directory - Tweak debian/regression.sh to handle new file locations -- Kenneth J. Pronovici Mon, 28 Jun 2010 13:34:59 -0500 pychecker (0.8.18-4) unstable; urgency=low * Bump standards version to 3.8.4 (no packaging changes). * Fix FTBFS caused by switch to Python2.6 as default (closes: #571504). - The failures were all due to unit test expectations that differ - Fixed various test cases to match 2.6, but this breaks build for 2.5 - Changed debian/regression.sh so test failures no longer kill the build - Tweaked debian/rules to remove old failed test results on clean -- Kenneth J. Pronovici Sun, 28 Feb 2010 16:44:46 +0000 pychecker (0.8.18-3) unstable; urgency=low * Fix warnings/problems indicated on package tracking page. - Bump standards version to 3.8.3 (no packaging changes) - Fix spelling error in debian/pychecker.1 ("accomodate") - Add ${misc:Depends} for all binary packages -- Kenneth J. Pronovici Sun, 10 Jan 2010 12:43:40 -0600 pychecker (0.8.18-2) unstable; urgency=low * Bump standards version to 3.8.1 (no packaging changes). * Bump debhelper compatibility to 7, per linitian recommendation. * Declare a dependency on debhelper (>= 7.0.1) to match compatibility. * Fix python/Python typo in debian/control to quiet lintian. -- Kenneth J. Pronovici Sun, 29 Mar 2009 18:02:10 -0500 pychecker (0.8.18-1) unstable; urgency=low * New upstream release. - Update Debian-specific results for unit tests, due to upstream changes. - Upstream release fixes Exception problems (closes: #487096). -- Kenneth J. Pronovici Sun, 24 Aug 2008 10:57:44 -0500 pychecker (0.8.17-9) unstable; urgency=low * Fix FTBTS due to unit test failures (closes: #477032). - The following tests failed: 3, 17, 22, 34, 48, 53, 71, 77, 87, 88 - All of these failures seem to be due to the move to Python 2.5 - Most of the failures are benign and have a simple explanation - A few look to be real regressions, and I have submitted upstream - Tests were fixed by adding Debian-specific expected results files -- Kenneth J. Pronovici Sun, 20 Apr 2008 22:19:32 -0500 pychecker (0.8.17-8) unstable; urgency=low * Fix IndexError exposed by git-buildpackage build (closes: #460357, #460698). - Apply patch from Guido Guenther fixing an if/elif mistake in warn.py - Submitted Guido's patch upstream as SF request #1889814 -- Kenneth J. Pronovici Fri, 8 Feb 2008 13:52:36 -0600 pychecker (0.8.17-7) unstable; urgency=low * Fix bad unit tests expectations that caused FTBFS (closes: #460355). - Added Debian-specific results for test3 (path to UserDict changed) - Remove Debian-specific results for test34 (path to GetoptError changed) -- Kenneth J. Pronovici Sat, 12 Jan 2008 10:17:59 -0600 pychecker (0.8.17-6) unstable; urgency=low * Apply patch from Dan O'Huiginn to improve manpage (closes: #456179). -- Kenneth J. Pronovici Thu, 20 Dec 2007 20:28:08 -0600 pychecker (0.8.17-5) unstable; urgency=low * Package the pychecker2 code in the upstream package (closes: #453092). - Modify upstream setup.py to include the pychecker2 package - Updated debian/README.Debian to discuss the state of the new code - Apply patches from Stani (http://pythonide.stani.be) to pychecker2/main.py * Tweaked description in debian/README.Debian to be more readable * Updated debian/copyright to add John Shue, who is now a project admin -- Kenneth J. Pronovici Wed, 5 Dec 2007 17:11:20 -0600 pychecker (0.8.17-4) unstable; urgency=low * Fix debian/watch by using qa.debian.org redirector (closes: #449766). -- Kenneth J. Pronovici Sun, 18 Nov 2007 18:15:39 -0600 pychecker (0.8.17-3) unstable; urgency=low * Add back support for $PYTHONVER in the pychecker script (closes: #384337). - Apply Jason Lunz's patch to debian/wrapper and add my own comments - Put back CHOICE OF PYTHON VERSION in debian/pychecker.1 - Update README.debian to reflect these changes * Make regression tests pass with new default Python, version 2.4. - Create test_expected/test3-debian (spurious path difference) - Create test_expected/test34-debian (spurious path difference) - Remove test_expected/test68-debian (no longer needed) - Remove test_expected/test85-debian (no longer needed) -- Kenneth J. Pronovici Wed, 23 Aug 2006 20:12:36 -0500 pychecker (0.8.17-2) unstable; urgency=low * Bumped Standards-Version to 3.7.2. - Provide empty binary-arch target in debian/rules to quiet lintian * Updated debian/copyright to include new Google annotation. * Update to latest Python policy using python-support method. - Change debian/control to use Build-Depends instead of Build-Depends-Indep - Change debian/rules to build using /usr/bin/python, not /usr/bin/python2.4 - Change debian/control to use Depends: ${python:Depends} - Change debian/rules to invoke dh_pysupport -d (for ${python:Depends}) - Change debian/pychecker.dirs to reference usr/share/python-support - Change debian/rules to build using --install-purelib, not --prefix - Change debian/pychecker.install to match new build locations - Change debian/pychecker.preinst to remove old package's pyo and pyc files - Rework debian/wrapper to find checker.py in its new location - Remove debian/pychecker.postinst and debian/pychecker.prerm - Added new debian/pyversions file for use by python-support * Remove support for $PYTHONVER in the pychecker command-line script. - This cannot really be done well with the new policy and infrastructure - Removed CHOICE OF PYTHON VERSION section from debian/pychecker.1 - Reworked debian/README.Debian to discuss this loss of functionality * Update regression tests to match new build process. - Change debian/regression.sh to use /usr/bin/python - Create test68-debian and test85-debian for Debian-specific results -- Kenneth J. Pronovici Sun, 23 Jul 2006 18:30:24 -0500 pychecker (0.8.17-1) unstable; urgency=low * New upstream release. * Update Debian package regression testing - Add test98 to debian/regression.list - Update debian-specific results in test_expected/test77-debian - Add '--limit 0' to checker.py call in regression.sh (per Neal) * Remove all dependencies on python2.1 and python2.2 (closes: #362464). * Make changes so that the default python is python2.4. - Use python2.4 in Depends and Build-Depends-Indep in debian/control - Update README.Debian and manpage discussion of python versions - Change interpreter search order debian/pychecker.postinst - Change interpreter search order debian/wrapper - Change debian/pychecker.install to look in python2.4 directory - Change debian/regression.sh to use python2.4 interpreter - Change debian/rules to use python2.4 interpreter - Remove debian-specific test results for test 3, 34, 68 and 85 -- Kenneth J. Pronovici Sat, 15 Apr 2006 10:12:38 -0500 pychecker (0.8.16-2) unstable; urgency=low * Fix a few README.Debian lines longer than 80 characters (closes: #337707). * Modify debian/rules to remove test_expected/*.results on clean (closes: #341564). * Comment in debian/rules that build will fail if any regression test fails. * Add a few comments to debian/rules about how regression tests work. * Add test96 and test97 to debian/regression.list (missed them before). -- Kenneth J. Pronovici Fri, 2 Dec 2005 14:02:37 -0600 pychecker (0.8.16-1) unstable; urgency=low * New upstream release. * Incorporate new setup.py with my changes from upstream CVS. * Use /bin/bash in debian/pychecker.prerm; lintian says it contains "bashisms". * Fix comments at top of debian/pychecker.preinst and debian/pychecker.prerm. -- Kenneth J. Pronovici Sat, 1 Oct 2005 10:27:38 -0500 pychecker (0.8.15-1) unstable; urgency=low * New upstream release. * Bumped Standards-Version to 3.6.2 (no packaging changes). * Added post-release tweak to setup.py from upstream CVS. -- Kenneth J. Pronovici Fri, 2 Sep 2005 11:37:14 -0500 pychecker (0.8.14-6) unstable; urgency=low * Support Python 2.4 in wrapper and in postinst. * Rework pychecker postinst so that it works for people who have Python set up to use alternatives (closes: #300922). I now have to invoke compileall.compile_dir() rather than compileally.py because I can't be sure of the location of compileall.py. -- Kenneth J. Pronovici Wed, 23 Mar 2005 16:23:09 -0600 pychecker (0.8.14-5) unstable; urgency=low * Rework pychecker postinst so that it works even for people who don't have the default python package installed. The fix is to look for python, python2.3, python2.2 and python2.1 (in that order), and use the first one found to compile the modules. * Update README.Debian to match new behavior in postinst. * Added notes in executable wrappers to document new behavior in postinst. -- Kenneth J. Pronovici Mon, 28 Feb 2005 13:00:50 -0600 pychecker (0.8.14-4) unstable; urgency=low * Fix my various screw-ups in the last release, with upstream's help. - Fall back to 0.8.14-1 and add correct changes one-by-one - Apply my patch.bug270924 to fix #270924 - Merge in upstream CVS checker.py and OP.py to fix #278588 - Merge in upstream CVS regression test #73 and tweak it to work - Fix Debian-specific results for regresson test #77 - Place test1002 and test1003 into debian/regression.list -- Kenneth J. Pronovici Mon, 20 Dec 2004 19:31:44 -0600 pychecker (0.8.14-3) unstable; urgency=low * Roll back change for #278588 in favor of upstream's equivalent fix. - Change checker.py to use NotImplementedError to indicate abstract methods - Get rid of ignore list for error in Config.py and CodeChecks.py - Remove documentation of ignore list from pycheckrc file - Pulled updated test #73 from upstream CVS, and tweaked to work - Tweaked test #77 to work with new line numbers in checker.py -- Kenneth J. Pronovici Fri, 17 Dec 2004 20:54:09 -0600 pychecker (0.8.14-2) unstable; urgency=low * Added warning to output of debian/regression.sh about ~/.pycheckrc. * Fix spurious division warnings for certain expressions (closes: #270924). - Made minor changes to CodeChecks.py to ignore "unknown" types in check - Created test1002 regression test and listed it in debian/regression.list * Fix spurious warnings about methods in built-in Set classes (closes: #278588). - Made changes to CodeChecks.py and Config.py to create ignore list for error - Added documentation for new ignore list into default pycheckrc file - Created test1003 regression test and listed it in debian/regression.list -- Kenneth J. Pronovici Tue, 23 Nov 2004 13:01:09 -0600 pychecker (0.8.14-1) unstable; urgency=low * New upstream release (incorporates fixes to earlier Debian bugs). -- Kenneth J. Pronovici Thu, 8 Jul 2004 17:54:29 -0500 pychecker (0.8.13-3) unstable; urgency=low * Bumped standards version to 3.6.1 (no changes). * Fix warnings about missing __module__ in C extensions (closes: #250425). - Applied patch from Bastian Kleineidam - Upstream recommended going ahead and applying patch - Can't add new regression test since this only happens for C extensions - Tweaked results in test77-debian because line numbers changed -- Kenneth J. Pronovici Sun, 23 May 2004 13:36:09 -0500 pychecker (0.8.13-2) unstable; urgency=low * Update Debian-specific manpage to discuss $PYTHONVER use. * Fix problem where 'sets = "sets"' causes warning (closes: #237503). - Made minor change to CodeChecks.py to avoid this warning for constants - Created test1001 regression test and listed it in debian/regression.list - Submitted patch upstream; no response after 2+ weeks, so I'm uploading -- Kenneth J. Pronovici Tue, 30 Mar 2004 20:37:20 -0600 pychecker (0.8.13-1) unstable; urgency=low * New upstream release. - This release incorporates a different upstream fix for #210682 - Comment in README.Debian that Python 1.5.2 is no longer supported - Commented out sections of setup.py that create pychecker script - Made debian/rules create $(install_dir)/bin before installing to it - Renamed Debian-specific test93 to test1000, to avoid clash with upstream - Added test93, test94, test95, test1000 to debian/regression.list - Modified Debian results for test1, test3, test4, test34, test77, test85 - Removed Debian results for test87 -- Kenneth J. Pronovici Thu, 20 Nov 2003 11:14:33 -0600 pychecker (0.8.12-5) unstable; urgency=low * Try to deal adequately with unicode format strings (closes: #210682) - The fix, in CodeChecks.py, looks sensible but might be a band-aid - I suspect that unicode identifiers might cause similar problems * Added Debian-specific regression tests to build process - Created debian/regression.sh based on test_check.sh - Created debian/regression.list as list of tests to run - Added test93 to test regressions related to bug #210682 (see above) - Created set of Debian-specific results for failing tests - Now run 'sh debian/regression.sh' in debian/rules -- Kenneth J. Pronovici Sat, 13 Sep 2003 19:33:36 -0500 pychecker (0.8.12-4) unstable; urgency=low * Added debian/compat file. * Bumped standards version to 3.5.9. * Updated debian/wrapper script (closes: #193955) - Handle command-line arguments containing spaces - Propogate exit code from command - Added python2.3 to list of interpreters - Now use ${} syntax to reference all variables * Now install modules to /usr/lib/site-python (closes: #137320) - Completely rewrote debian/rules file - Updated README.Debian to discuss new location - Changed debhelper build-dependency to (>= 4.1) - Added build-dependency on python2.3-dev - Added install dependency on python2.3 - Commented out data_files piece in setup.py - Removed #!/usr/bin/env lines from module files - Added debian/pychecker.dirs - Added debian/pychecker.examples - Added debian/pychecker.install - Added debian/pychecker.manpages - Added debian/pychecker.postinst - Added debian/pychecker.preinst - Added debian/pychecker.prerm -- Kenneth J. Pronovici Thu, 11 Sep 2003 11:30:05 -0500 pychecker (0.8.12-3) unstable; urgency=low * New maintainer (closes: #200976). - Updated debian/control to list me as maintainer - Updated debian/copyright to list me as maintainer - Added debian/watch for my own housekeeping - Some lintian warnings remain; I'll address them later - Some bugs remain open; I'll address them later also -- Kenneth J. Pronovici Mon, 8 Sep 2003 20:55:40 -0500 pychecker (0.8.12-2) unstable; urgency=low * Updated manpage, thanks Fredrik Steen (Closes: Bug#181461) * Slight change to debian/copyright to make lintian happy -- Arto Jantunen Fri, 21 Mar 2003 16:27:18 +0200 pychecker (0.8.12-1) unstable; urgency=low * New upstream release * Updated Standards-Version to 3.5.8.0 (no changes) -- Arto Jantunen Sun, 29 Dec 2002 20:55:33 +0200 pychecker (0.8.11-2) unstable; urgency=low * Made python2.2 the default and removed support for python1.5 and python2, as requested. -- Arto Jantunen Thu, 29 Aug 2002 19:09:17 +0300 pychecker (0.8.11-1) unstable; urgency=low * New upstream release -- Arto Jantunen Sun, 9 Jun 2002 15:41:06 +0300 pychecker (0.8.10-1) unstable; urgency=low * New upstream release -- Arto Jantunen Thu, 21 Mar 2002 19:47:05 +0200 pychecker (0.8.9-1) unstable; urgency=low * New upstream release * Replaced the wrapper with Justin Hahn's version. -- Arto Jantunen Sun, 3 Feb 2002 21:00:37 +0200 pychecker (0.8.8-2) unstable; urgency=medium * Fixed the wrapper, thanks to Tom Culliton for letting me know that it's broken. (really broken, this needs to go into woody) -- Arto Jantunen Thu, 17 Jan 2002 12:48:44 +0200 pychecker (0.8.8-1) unstable; urgency=low * New upstream release -- Arto Jantunen Mon, 14 Jan 2002 18:40:50 +0200 pychecker (0.8.7-1) unstable; urgency=low * New upstream release -- Arto Jantunen Mon, 7 Jan 2002 19:35:28 +0200 pychecker (0.8.6-1) unstable; urgency=low * New upstream release -- Arto Jantunen Sat, 17 Nov 2001 16:15:00 +0200 pychecker (0.8.5-2) unstable; urgency=low * Made the wrapper script support python2.1, python2.2, python2 and python1.5 (all versions in the archive atm) * Changed Depends: to fit the change * Stopped compiling stuff in the postinst (doesn't make sense after the other changes) and relocated pychecker to /usr/share * Also you can choose which python version to use by setting $PYTHONVER to the version number you desire (Added README.Debian to explain this) -- Arto Jantunen Tue, 6 Nov 2001 20:50:31 +0200 pychecker (0.8.5-1) unstable; urgency=low * New upstream release * Changed depends to python2.1 | python1.5 (Closes: Bug#105704) -- Arto Jantunen Thu, 18 Oct 2001 16:49:34 +0300 pychecker (0.8.4-1) unstable; urgency=low * New upstream release * Changed Build-Depends to Build-Depends-Indep to silence lintian * Updated to Standards-Version 3.5.6.0 -- Arto Jantunen Sun, 30 Sep 2001 15:45:04 +0300 pychecker (0.8.3-1) unstable; urgency=low * New upstream release -- Arto Jantunen Tue, 18 Sep 2001 18:31:15 +0300 pychecker (0.8.1-1) unstable; urgency=low * New upstream release (Closes: Bug#108023) -- Arto Jantunen Fri, 10 Aug 2001 12:32:03 +0300 pychecker (0.7.5-1) unstable; urgency=low * New upstream release * Removed unwanted dependency to python-base (only depends on python now) -- Arto Jantunen Mon, 23 Jul 2001 23:01:27 +0300 pychecker (0.7-1) unstable; urgency=low * New upstream release * Small change to debian/rules to fix some silly problems -- Arto Jantunen Tue, 17 Jul 2001 16:39:21 +0300 pychecker (0.6.1-1) unstable; urgency=medium * New upstream version (Closes: Bug#102840) -- Arto Jantunen Mon, 9 Jul 2001 21:58:55 +0300 pychecker (0.5-2) unstable; urgency=low * Wrote a manpage * Made the postinst compile all .py's (naturally the prerm removes them) -- Arto Jantunen Mon, 18 Jun 2001 02:00:42 +0300 pychecker (0.5-1) unstable; urgency=low * Initial Release. -- Arto Jantunen Wed, 30 May 2001 12:53:56 +0300 debian/compat0000664000000000000000000000000212143254543010371 0ustar 9 debian/watch0000664000000000000000000000007212143254543010223 0ustar version=3 http://sf.net/pychecker/pychecker-(.*)\.tar\.gz debian/rules0000775000000000000000000000071612143254543010257 0ustar #!/usr/bin/make -f # Set to enable verbose output from debhelper #export DH_VERBOSE=1 install_dir = debian/tmp %: dh $@ --with python2 override_dh_compress: dh_compress -X.py override_dh_auto_install: mkdir -p $(install_dir)/bin cp debian/wrapper $(install_dir)/bin/pychecker dh_auto_install -- --root $(install_dir) --install-purelib lib/pychecker override_dh_auto_test: ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) sh debian/regression.sh endif