Merge lp:~darkmuggle-deactivatedaccount/ubuntu/oneiric/pep8/oneiric into lp:ubuntu/oneiric/pep8

Proposed by Ben Howard
Status: Superseded
Proposed branch: lp:~darkmuggle-deactivatedaccount/ubuntu/oneiric/pep8/oneiric
Merge into: lp:ubuntu/oneiric/pep8
Diff against target: 1103 lines (+460/-181)
15 files modified
CHANGES.txt (+45/-1)
PKG-INFO (+66/-7)
README.rst (+15/-4)
TODO.txt (+5/-1)
debian/changelog (+7/-0)
debian/control (+1/-1)
debian/docs (+0/-1)
debian/python-pep8.postinst.debhelper (+0/-5)
debian/python-pep8.prerm.debhelper (+0/-5)
debian/python-pep8.substvars (+0/-4)
debian/rules (+4/-0)
pep8.egg-info/PKG-INFO (+66/-7)
pep8.egg-info/SOURCES.txt (+1/-1)
pep8.py (+249/-143)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~darkmuggle-deactivatedaccount/ubuntu/oneiric/pep8/oneiric
Reviewer Review Type Date Requested Status
James Page Needs Fixing
Ubuntu Sponsors Pending
Review via email: mp+70454@code.launchpad.net

Commit message

 New upstream release (LP: #817270)

Description of the change

New upstream release (LP: #817270)

To post a comment you must log in.
Revision history for this message
James Page (james-page) wrote :

Hi Ben

I have the following feedback on your merge proposal:

lintian throws some warnings and an error against the source package:

1) debhelper files in debian directory

W: pep8 source: diff-contains-substvars debian/python-pep8.substvars
E: pep8 source: temporary-debhelper-file python-pep8.prerm.debhelper and 1 other

The debian folder contains some temp files created by debhelper; these should be removed:

python-pep8.debhelper.log
python-pep8.postinst.debhelper
python-pep8.prerm.debhelper
python-pep8.substvars

2) Standards-Version is out of date

W: pep8 source: out-of-date-standards-version 3.8.4 (current is 3.9.2)

New upstream releases are a good opportunity to bump the standards version of a package; latest is 3.9.2

See /usr/share/doc/debian-policy/upgrading-checklist.txt.gz for details of what to check but as this is a simple package I would expect minimal/no-change. This should be documented in the changelog as well.

3) dh_python2 transition

Chucks changes from version 0.5.0-1ubuntu1 have been reverted; please re-instate.

See http://wiki.debian.org/Python/TransitionToDHPython2 for more details.

..and a couple against the resulting binary package (see these by running lintian -i -I --show-overrides against the resulting .changes file)

1) Package source format

I: pep8 source: missing-debian-source-format

Ideally the package should specify the source format '3.0 (quilt)' in debian/source/format.

See http://wiki.debian.org/Projects/DebSrc3.0

2) Upstream changelog name

W: pep8: wrong-name-for-upstream-changelog usr/share/doc/pep8/CHANGES.txt

The upstream changelog should be installed to /usr/share/doc/pep8/changelog.gz; you can do this be overriding dh_installchangelogs in debian/rules:

override_dh_installchangelogs:
    dh_installchangelogs CHANGES.txt

You will need to remove it from debian/docs as well. Interestingly enough pkgbinarymangler then removes this file but this is the right way todo so that the distro chooses whether to retain it or not.

Its worth reviewing the lintian output again once these changes are made as it may reveal other warnings/errors.

You can just re-push your changes back to this branch and the merge proposal will update.

Cheers

James

review: Needs Fixing
Revision history for this message
Ben Howard (darkmuggle-deactivatedaccount) wrote :

Updated per review. Passed through litian without error.

Revision history for this message
Ben Howard (darkmuggle-deactivatedaccount) wrote :

Updated to the latest Debian upstream release for PEP8.

7. By Ben Howard

* Merge from debian unstable. (LP: #817270) Remaining Changes:
  - dh_python2 transition.
* New upstream release. (Closes: #635562)
* Remove depends on python-setuptools. (Closes: #581019)
* Update Standards version, no changes needed.

Unmerged revisions

7. By Ben Howard

* Merge from debian unstable. (LP: #817270) Remaining Changes:
  - dh_python2 transition.
* New upstream release. (Closes: #635562)
* Remove depends on python-setuptools. (Closes: #581019)
* Update Standards version, no changes needed.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CHANGES.txt'
--- CHANGES.txt 2010-03-16 19:18:00 +0000
+++ CHANGES.txt 2011-08-05 17:38:30 +0000
@@ -1,6 +1,50 @@
1Changelog1Changelog
2=========2=========
33
40.6.1 (2010-10-03)
5------------------
6
7* Fixed inconsistent version numbers. (Issue #21)
8
9
100.6.0 (2010-09-19)
11------------------
12
13* Test suite reorganized and enhanced in order to check more failures
14 with fewer test files. Read the ``run_tests`` docstring for details
15 about the syntax.
16
17* Fix E225: accept ``print >>sys.stderr, "..."`` syntax.
18
19* Fix E501 for lines containing multibyte encoded characters. (Issue #7)
20
21* Fix E221, E222, E223, E224 not detected in some cases. (Issue #16)
22
23* Fix E211 to reject ``v = dic['a'] ['b']``. (Issue #17)
24
25* Exit code is always 1 if any error or warning is found. (Issue #10)
26
27* ``--ignore`` checks are now really ignored, especially in
28 conjunction with ``--count``. (Issue #8)
29
30* Blank lines with spaces yield W293 instead of W291: some developers
31 want to ignore this warning and indent the blank lines to paste their
32 code easily in the Python interpreter.
33
34* Fix E301: do not require a blank line before an indented block. (Issue #14)
35
36* Fix E203 to accept NumPy slice notation ``a[0, :]``. (Issue #13)
37
38* Performance improvements.
39
40* Fix decoding and checking non-UTF8 files in Python 3.
41
42* Fix E225: reject ``True+False`` when running on Python 3.
43
44* Fix an exception when the line starts with an operator.
45
46* Allow a new line before closing ``)``, ``}`` or ``]``. (Issue #5)
47
448
50.5.0 (2010-02-17)490.5.0 (2010-02-17)
6------------------50------------------
@@ -63,7 +107,7 @@
63107
64* E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)108* E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)
65109
66* Spaces are not longer required around the equals sign for keyword110* Spaces are no longer required around the equals sign for keyword
67 arguments or default parameter values.111 arguments or default parameter values.
68112
69113
70114
=== modified file 'PKG-INFO'
--- PKG-INFO 2010-03-16 19:18:00 +0000
+++ PKG-INFO 2011-08-05 17:38:30 +0000
@@ -1,6 +1,6 @@
1Metadata-Version: 1.01Metadata-Version: 1.0
2Name: pep82Name: pep8
3Version: 0.5.03Version: 0.6.1
4Summary: Python style guide checker4Summary: Python style guide checker
5Home-page: http://github.com/jcrocholl/pep85Home-page: http://github.com/jcrocholl/pep8
6Author: Johann C. Rocholl6Author: Johann C. Rocholl
@@ -30,14 +30,25 @@
30 * Small: Just one Python file, requires only stdlib. You can use just30 * Small: Just one Python file, requires only stdlib. You can use just
31 the pep8.py file for this purpose.31 the pep8.py file for this purpose.
32 32
33 * Easy_installable, of course!33 * Comes with a comprehensive test suite.
34
35 34
36 Installation35 Installation
37 ------------36 ------------
38 37
39 Just an ``easy_install pep8`` ought to do the trick.38 You can install, upgrade, uninstall pep8.py with these commands::
40 39
40 $ sudo pip install pep8
41 $ sudo pip install --upgrade pep8
42 $ sudo pip uninstall pep8
43
44 Or if you don't have `pip`::
45
46 $ sudo easy_install pep8
47
48 There's also a package for Debian/Ubuntu, but it's not always the
49 latest version::
50
51 $ sudo apt-get install pep8
41 52
42 Example usage and output53 Example usage and output
43 ------------------------54 ------------------------
@@ -127,6 +138,50 @@
127 Changelog138 Changelog
128 =========139 =========
129 140
141 0.6.1 (2010-10-03)
142 ------------------
143
144 * Fixed inconsistent version numbers. (Issue #21)
145
146
147 0.6.0 (2010-09-19)
148 ------------------
149
150 * Test suite reorganized and enhanced in order to check more failures
151 with fewer test files. Read the ``run_tests`` docstring for details
152 about the syntax.
153
154 * Fix E225: accept ``print >>sys.stderr, "..."`` syntax.
155
156 * Fix E501 for lines containing multibyte encoded characters. (Issue #7)
157
158 * Fix E221, E222, E223, E224 not detected in some cases. (Issue #16)
159
160 * Fix E211 to reject ``v = dic['a'] ['b']``. (Issue #17)
161
162 * Exit code is always 1 if any error or warning is found. (Issue #10)
163
164 * ``--ignore`` checks are now really ignored, especially in
165 conjunction with ``--count``. (Issue #8)
166
167 * Blank lines with spaces yield W293 instead of W291: some developers
168 want to ignore this warning and indent the blank lines to paste their
169 code easily in the Python interpreter.
170
171 * Fix E301: do not require a blank line before an indented block. (Issue #14)
172
173 * Fix E203 to accept NumPy slice notation ``a[0, :]``. (Issue #13)
174
175 * Performance improvements.
176
177 * Fix decoding and checking non-UTF8 files in Python 3.
178
179 * Fix E225: reject ``True+False`` when running on Python 3.
180
181 * Fix an exception when the line starts with an operator.
182
183 * Allow a new line before closing ``)``, ``}`` or ``]``. (Issue #5)
184
130 185
131 0.5.0 (2010-02-17)186 0.5.0 (2010-02-17)
132 ------------------187 ------------------
@@ -189,7 +244,7 @@
189 244
190 * E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)245 * E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)
191 246
192 * Spaces are not longer required around the equals sign for keyword247 * Spaces are no longer required around the equals sign for keyword
193 arguments or default parameter values.248 arguments or default parameter values.
194 249
195 250
@@ -221,7 +276,11 @@
221 TODO276 TODO
222 ====277 ====
223 278
224 - ...279 - Should command line option --repeat be enabled by default?
280
281 - Does command line option --ignore properly prevent status code 1?
282
283 - Release version 1.0 after a brief stabilization period.
225 284
226Keywords: pep8285Keywords: pep8
227Platform: UNKNOWN286Platform: UNKNOWN
228287
=== modified file 'README.rst'
--- README.rst 2010-03-16 19:18:00 +0000
+++ README.rst 2011-08-05 17:38:30 +0000
@@ -22,14 +22,25 @@
22* Small: Just one Python file, requires only stdlib. You can use just22* Small: Just one Python file, requires only stdlib. You can use just
23 the pep8.py file for this purpose.23 the pep8.py file for this purpose.
2424
25* Easy_installable, of course!25* Comes with a comprehensive test suite.
26
2726
28Installation27Installation
29------------28------------
3029
31Just an ``easy_install pep8`` ought to do the trick.30You can install, upgrade, uninstall pep8.py with these commands::
3231
32 $ sudo pip install pep8
33 $ sudo pip install --upgrade pep8
34 $ sudo pip uninstall pep8
35
36Or if you don't have `pip`::
37
38 $ sudo easy_install pep8
39
40There's also a package for Debian/Ubuntu, but it's not always the
41latest version::
42
43 $ sudo apt-get install pep8
3344
34Example usage and output45Example usage and output
35------------------------46------------------------
3647
=== modified file 'TODO.txt'
--- TODO.txt 2010-03-16 19:18:00 +0000
+++ TODO.txt 2011-08-05 17:38:30 +0000
@@ -1,4 +1,8 @@
1TODO1TODO
2====2====
33
4- ...4- Should command line option --repeat be enabled by default?
5
6- Does command line option --ignore properly prevent status code 1?
7
8- Release version 1.0 after a brief stabilization period.
59
=== modified file 'debian/changelog'
--- debian/changelog 2011-07-07 09:09:25 +0000
+++ debian/changelog 2011-08-05 17:38:30 +0000
@@ -1,3 +1,10 @@
1pep8 (0.6.1-0ubuntu1) oneiric; urgency=low
2
3 * New upstream release (LP: #817270)
4 * Switch to dpkg-source 3.0 (quilt) format
5
6 -- Ben Howard <ben.howard@canonical.com> Fri, 05 Aug 2011 08:45:10 -0600
7
1pep8 (0.5.0-1ubuntu1) oneiric; urgency=low8pep8 (0.5.0-1ubuntu1) oneiric; urgency=low
29
3 * dh_python2 transition. 10 * dh_python2 transition.
411
=== modified file 'debian/control'
--- debian/control 2011-07-07 09:09:25 +0000
+++ debian/control 2011-08-05 17:38:30 +0000
@@ -5,7 +5,7 @@
5XSBC-Original-Maintainer: David Watson <david@bashton.com>5XSBC-Original-Maintainer: David Watson <david@bashton.com>
6Uploaders: David Watson <dwatson@debian.org>6Uploaders: David Watson <dwatson@debian.org>
7Build-Depends: debhelper (>= 7), python-all (>= 2.6.6-3~), python-setuptools7Build-Depends: debhelper (>= 7), python-all (>= 2.6.6-3~), python-setuptools
8Standards-Version: 3.8.48Standards-Version: 3.9.2
9Homepage: http://pypi.python.org/pypi/pep89Homepage: http://pypi.python.org/pypi/pep8
1010
11Package: pep811Package: pep8
1212
=== modified file 'debian/docs'
--- debian/docs 2009-10-23 10:11:07 +0000
+++ debian/docs 2011-08-05 17:38:30 +0000
@@ -1,3 +1,2 @@
1CHANGES.txt
2README.rst1README.rst
3TODO.txt2TODO.txt
43
=== removed file 'debian/python-pep8.postinst.debhelper'
--- debian/python-pep8.postinst.debhelper 2009-10-23 10:11:07 +0000
+++ debian/python-pep8.postinst.debhelper 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1# Automatically added by dh_pysupport
2if which update-python-modules >/dev/null 2>&1; then
3 update-python-modules python-pep8.public
4fi
5# End automatically added section
60
=== removed file 'debian/python-pep8.prerm.debhelper'
--- debian/python-pep8.prerm.debhelper 2009-10-23 10:11:07 +0000
+++ debian/python-pep8.prerm.debhelper 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1# Automatically added by dh_pysupport
2if which update-python-modules >/dev/null 2>&1; then
3 update-python-modules -c python-pep8.public
4fi
5# End automatically added section
60
=== removed file 'debian/python-pep8.substvars'
--- debian/python-pep8.substvars 2009-10-23 10:11:07 +0000
+++ debian/python-pep8.substvars 1970-01-01 00:00:00 +0000
@@ -1,4 +0,0 @@
1python:Versions=2.4, 2.5
2python:Provides=python2.4-pep8, python2.5-pep8
3python:Depends=python, python-support (>= 0.90.0)
4misc:Depends=
50
=== modified file 'debian/rules'
--- debian/rules 2011-07-07 09:09:25 +0000
+++ debian/rules 2011-08-05 17:38:30 +0000
@@ -11,3 +11,7 @@
1111
12%:12%:
13 dh $@ --with python213 dh $@ --with python2
14
15override_dh_installchangelogs:
16 dh_installchangelogs CHANGES.txt
17
1418
=== modified file 'pep8.egg-info/PKG-INFO'
--- pep8.egg-info/PKG-INFO 2010-03-16 19:18:00 +0000
+++ pep8.egg-info/PKG-INFO 2011-08-05 17:38:30 +0000
@@ -1,6 +1,6 @@
1Metadata-Version: 1.01Metadata-Version: 1.0
2Name: pep82Name: pep8
3Version: 0.5.03Version: 0.6.1
4Summary: Python style guide checker4Summary: Python style guide checker
5Home-page: http://github.com/jcrocholl/pep85Home-page: http://github.com/jcrocholl/pep8
6Author: Johann C. Rocholl6Author: Johann C. Rocholl
@@ -30,14 +30,25 @@
30 * Small: Just one Python file, requires only stdlib. You can use just30 * Small: Just one Python file, requires only stdlib. You can use just
31 the pep8.py file for this purpose.31 the pep8.py file for this purpose.
32 32
33 * Easy_installable, of course!33 * Comes with a comprehensive test suite.
34
35 34
36 Installation35 Installation
37 ------------36 ------------
38 37
39 Just an ``easy_install pep8`` ought to do the trick.38 You can install, upgrade, uninstall pep8.py with these commands::
40 39
40 $ sudo pip install pep8
41 $ sudo pip install --upgrade pep8
42 $ sudo pip uninstall pep8
43
44 Or if you don't have `pip`::
45
46 $ sudo easy_install pep8
47
48 There's also a package for Debian/Ubuntu, but it's not always the
49 latest version::
50
51 $ sudo apt-get install pep8
41 52
42 Example usage and output53 Example usage and output
43 ------------------------54 ------------------------
@@ -127,6 +138,50 @@
127 Changelog138 Changelog
128 =========139 =========
129 140
141 0.6.1 (2010-10-03)
142 ------------------
143
144 * Fixed inconsistent version numbers. (Issue #21)
145
146
147 0.6.0 (2010-09-19)
148 ------------------
149
150 * Test suite reorganized and enhanced in order to check more failures
151 with fewer test files. Read the ``run_tests`` docstring for details
152 about the syntax.
153
154 * Fix E225: accept ``print >>sys.stderr, "..."`` syntax.
155
156 * Fix E501 for lines containing multibyte encoded characters. (Issue #7)
157
158 * Fix E221, E222, E223, E224 not detected in some cases. (Issue #16)
159
160 * Fix E211 to reject ``v = dic['a'] ['b']``. (Issue #17)
161
162 * Exit code is always 1 if any error or warning is found. (Issue #10)
163
164 * ``--ignore`` checks are now really ignored, especially in
165 conjunction with ``--count``. (Issue #8)
166
167 * Blank lines with spaces yield W293 instead of W291: some developers
168 want to ignore this warning and indent the blank lines to paste their
169 code easily in the Python interpreter.
170
171 * Fix E301: do not require a blank line before an indented block. (Issue #14)
172
173 * Fix E203 to accept NumPy slice notation ``a[0, :]``. (Issue #13)
174
175 * Performance improvements.
176
177 * Fix decoding and checking non-UTF8 files in Python 3.
178
179 * Fix E225: reject ``True+False`` when running on Python 3.
180
181 * Fix an exception when the line starts with an operator.
182
183 * Allow a new line before closing ``)``, ``}`` or ``]``. (Issue #5)
184
130 185
131 0.5.0 (2010-02-17)186 0.5.0 (2010-02-17)
132 ------------------187 ------------------
@@ -189,7 +244,7 @@
189 244
190 * E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)245 * E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)
191 246
192 * Spaces are not longer required around the equals sign for keyword247 * Spaces are no longer required around the equals sign for keyword
193 arguments or default parameter values.248 arguments or default parameter values.
194 249
195 250
@@ -221,7 +276,11 @@
221 TODO276 TODO
222 ====277 ====
223 278
224 - ...279 - Should command line option --repeat be enabled by default?
280
281 - Does command line option --ignore properly prevent status code 1?
282
283 - Release version 1.0 after a brief stabilization period.
225 284
226Keywords: pep8285Keywords: pep8
227Platform: UNKNOWN286Platform: UNKNOWN
228287
=== modified file 'pep8.egg-info/SOURCES.txt'
--- pep8.egg-info/SOURCES.txt 2010-03-16 19:18:00 +0000
+++ pep8.egg-info/SOURCES.txt 2011-08-05 17:38:30 +0000
@@ -12,4 +12,4 @@
12pep8.egg-info/namespace_packages.txt12pep8.egg-info/namespace_packages.txt
13pep8.egg-info/not-zip-safe13pep8.egg-info/not-zip-safe
14pep8.egg-info/requires.txt14pep8.egg-info/requires.txt
15pep8.egg-info/top_level.txt15pep8.egg-info/top_level.txt
16\ No newline at end of file16\ No newline at end of file
1717
=== modified file 'pep8.py'
--- pep8.py 2010-03-16 19:18:00 +0000
+++ pep8.py 2011-08-05 17:38:30 +0000
@@ -92,34 +92,51 @@
9292
93"""93"""
9494
95__version__ = '0.5.0'95__version__ = '0.6.1'
9696
97import os97import os
98import sys98import sys
99import re99import re
100import time100import time
101import inspect101import inspect
102import keyword
102import tokenize103import tokenize
103from optparse import OptionParser104from optparse import OptionParser
104from keyword import iskeyword
105from fnmatch import fnmatch105from fnmatch import fnmatch
106try:
107 frozenset
108except NameError:
109 from sets import ImmutableSet as frozenset
110
106111
107DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git'112DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git'
108DEFAULT_IGNORE = ['E24']113DEFAULT_IGNORE = 'E24'
114MAX_LINE_LENGTH = 79
109115
110INDENT_REGEX = re.compile(r'([ \t]*)')116INDENT_REGEX = re.compile(r'([ \t]*)')
111RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)')117RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)')
112SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)')118SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)')
113ERRORCODE_REGEX = re.compile(r'[EW]\d{3}')119ERRORCODE_REGEX = re.compile(r'[EW]\d{3}')
114E301NOT_REGEX = re.compile(r'class |def |u?r?["\']')120DOCSTRING_REGEX = re.compile(r'u?r?["\']')
121WHITESPACE_AROUND_OPERATOR_REGEX = \
122 re.compile('([^\w\s]*)\s*(\t| )\s*([^\w\s]*)')
123EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
124WHITESPACE_AROUND_NAMED_PARAMETER_REGEX = \
125 re.compile(r'[()]|\s=[^=]|[^=!<>]=\s')
126
115127
116WHITESPACE = ' \t'128WHITESPACE = ' \t'
117129
118BINARY_OPERATORS = ['**=', '*=', '+=', '-=', '!=', '<>',130BINARY_OPERATORS = frozenset(['**=', '*=', '+=', '-=', '!=', '<>',
119 '%=', '^=', '&=', '|=', '==', '/=', '//=', '>=', '<=', '>>=', '<<=',131 '%=', '^=', '&=', '|=', '==', '/=', '//=', '<=', '>=', '<<=', '>>=',
120 '%', '^', '&', '|', '=', '/', '//', '>', '<', '>>', '<<']132 '%', '^', '&', '|', '=', '/', '//', '<', '>', '<<'])
121UNARY_OPERATORS = ['**', '*', '+', '-']133UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
122OPERATORS = BINARY_OPERATORS + UNARY_OPERATORS134OPERATORS = BINARY_OPERATORS | UNARY_OPERATORS
135SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.INDENT,
136 tokenize.DEDENT, tokenize.NEWLINE])
137E225NOT_KEYWORDS = (frozenset(keyword.kwlist + ['print']) -
138 frozenset(['False', 'None', 'True']))
139BENCHMARK_KEYS = ('directories', 'files', 'logical lines', 'physical lines')
123140
124options = None141options = None
125args = None142args = None
@@ -164,18 +181,33 @@
164181
165182
166def trailing_whitespace(physical_line):183def trailing_whitespace(physical_line):
167 """184 r"""
168 JCR: Trailing whitespace is superfluous.185 JCR: Trailing whitespace is superfluous.
186 FBM: Except when it occurs as part of a blank line (i.e. the line is
187 nothing but whitespace). According to Python docs[1] a line with only
188 whitespace is considered a blank line, and is to be ignored. However,
189 matching a blank line to its indentation level avoids mistakenly
190 terminating a multi-line statement (e.g. class declaration) when
191 pasting code into the standard Python interpreter.
192
193 [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines
194
195 The warning returned varies on whether the line itself is blank, for easier
196 filtering for those who want to indent their blank lines.
169197
170 Okay: spam(1)198 Okay: spam(1)
171 W291: spam(1)\s199 W291: spam(1)\s
200 W293: class Foo(object):\n \n bang = 12
172 """201 """
173 physical_line = physical_line.rstrip('\n') # chr(10), newline202 physical_line = physical_line.rstrip('\n') # chr(10), newline
174 physical_line = physical_line.rstrip('\r') # chr(13), carriage return203 physical_line = physical_line.rstrip('\r') # chr(13), carriage return
175 physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L204 physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
176 stripped = physical_line.rstrip()205 stripped = physical_line.rstrip()
177 if physical_line != stripped:206 if physical_line != stripped:
178 return len(stripped), "W291 trailing whitespace"207 if stripped:
208 return len(stripped), "W291 trailing whitespace"
209 else:
210 return 0, "W293 blank line contains whitespace"
179211
180212
181def trailing_blank_lines(physical_line, lines, line_number):213def trailing_blank_lines(physical_line, lines, line_number):
@@ -208,9 +240,18 @@
208 For flowing long blocks of text (docstrings or comments), limiting the240 For flowing long blocks of text (docstrings or comments), limiting the
209 length to 72 characters is recommended.241 length to 72 characters is recommended.
210 """242 """
211 length = len(physical_line.rstrip())243 line = physical_line.rstrip()
212 if length > 79:244 length = len(line)
213 return 79, "E501 line too long (%d characters)" % length245 if length > MAX_LINE_LENGTH:
246 try:
247 # The line could contain multi-byte characters
248 if not hasattr(line, 'decode'): # Python 3
249 line = line.encode('latin-1')
250 length = len(line.decode('utf-8'))
251 except UnicodeDecodeError:
252 pass
253 if length > MAX_LINE_LENGTH:
254 return MAX_LINE_LENGTH, "E501 line too long (%d characters)" % length
214255
215256
216##############################################################################257##############################################################################
@@ -219,7 +260,8 @@
219260
220261
221def blank_lines(logical_line, blank_lines, indent_level, line_number,262def blank_lines(logical_line, blank_lines, indent_level, line_number,
222 previous_logical, blank_lines_before_comment):263 previous_logical, previous_indent_level,
264 blank_lines_before_comment):
223 r"""265 r"""
224 Separate top-level function and class definitions with two blank lines.266 Separate top-level function and class definitions with two blank lines.
225267
@@ -252,7 +294,8 @@
252 logical_line.startswith('class ') or294 logical_line.startswith('class ') or
253 logical_line.startswith('@')):295 logical_line.startswith('@')):
254 if indent_level:296 if indent_level:
255 if not (max_blank_lines or E301NOT_REGEX.match(previous_logical)):297 if not (max_blank_lines or previous_indent_level < indent_level or
298 DOCSTRING_REGEX.match(previous_logical)):
256 return 0, "E301 expected 1 blank line, found 0"299 return 0, "E301 expected 1 blank line, found 0"
257 elif max_blank_lines != 2:300 elif max_blank_lines != 2:
258 return 0, "E302 expected 2 blank lines, found %d" % max_blank_lines301 return 0, "E302 expected 2 blank lines, found %d" % max_blank_lines
@@ -279,18 +322,17 @@
279 E203: if x == 4 : print x, y; x, y = y, x322 E203: if x == 4 : print x, y; x, y = y, x
280 """323 """
281 line = logical_line324 line = logical_line
282 for char in '([{':325 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
283 found = line.find(char + ' ')326 text = match.group()
284 if found > -1:327 char = text.strip()
328 found = match.start()
329 if text == char + ' ' and char in '([{':
285 return found + 1, "E201 whitespace after '%s'" % char330 return found + 1, "E201 whitespace after '%s'" % char
286 for char in '}])':331 if text == ' ' + char and line[found - 1] != ',':
287 found = line.find(' ' + char)332 if char in '}])':
288 if found > -1 and line[found - 1] != ',':333 return found, "E202 whitespace before '%s'" % char
289 return found, "E202 whitespace before '%s'" % char334 if char in ',;:':
290 for char in ',;:':335 return found, "E203 whitespace before '%s'" % char
291 found = line.find(' ' + char)
292 if found > -1:
293 return found, "E203 whitespace before '%s'" % char
294336
295337
296def missing_whitespace(logical_line):338def missing_whitespace(logical_line):
@@ -370,9 +412,11 @@
370 if (token_type == tokenize.OP and412 if (token_type == tokenize.OP and
371 text in '([' and413 text in '([' and
372 start != prev_end and414 start != prev_end and
373 prev_type == tokenize.NAME and415 (prev_type == tokenize.NAME or prev_text in '}])') and
416 # Syntax "class A (B):" is allowed, but avoid it
374 (index < 2 or tokens[index - 2][1] != 'class') and417 (index < 2 or tokens[index - 2][1] != 'class') and
375 (not iskeyword(prev_text))):418 # Allow "return (a.foo for a in range(5))"
419 (not keyword.iskeyword(prev_text))):
376 return prev_end, "E211 whitespace before '%s'" % text420 return prev_end, "E211 whitespace before '%s'" % text
377 prev_type = token_type421 prev_type = token_type
378 prev_text = text422 prev_text = text
@@ -392,20 +436,16 @@
392 E223: a = 4\t+ 5436 E223: a = 4\t+ 5
393 E224: a = 4 +\t5437 E224: a = 4 +\t5
394 """438 """
395 line = logical_line439 for match in WHITESPACE_AROUND_OPERATOR_REGEX.finditer(logical_line):
396 for operator in OPERATORS:440 before, whitespace, after = match.groups()
397 found = line.find(' ' + operator)441 tab = whitespace == '\t'
398 if found > -1:442 offset = match.start(2)
399 return found, "E221 multiple spaces before operator"443 if before in OPERATORS:
400 found = line.find(operator + ' ')444 return offset, (tab and "E224 tab after operator" or
401 if found > -1:445 "E222 multiple spaces after operator")
402 return found, "E222 multiple spaces after operator"446 elif after in OPERATORS:
403 found = line.find('\t' + operator)447 return offset, (tab and "E223 tab before operator" or
404 if found > -1:448 "E221 multiple spaces before operator")
405 return found, "E223 tab before operator"
406 found = line.find(operator + '\t')
407 if found > -1:
408 return found, "E224 tab after operator"
409449
410450
411def missing_whitespace_around_operator(logical_line, tokens):451def missing_whitespace_around_operator(logical_line, tokens):
@@ -451,20 +491,29 @@
451 elif text == ')':491 elif text == ')':
452 parens -= 1492 parens -= 1
453 if need_space:493 if need_space:
454 if start == prev_end:494 if start != prev_end:
495 need_space = False
496 elif text == '>' and prev_text == '<':
497 # Tolerate the "<>" operator, even if running Python 3
498 pass
499 else:
455 return prev_end, "E225 missing whitespace around operator"500 return prev_end, "E225 missing whitespace around operator"
456 need_space = False501 elif token_type == tokenize.OP and prev_end is not None:
457 elif token_type == tokenize.OP:
458 if text == '=' and parens:502 if text == '=' and parens:
459 # Allow keyword args or defaults: foo(bar=None).503 # Allow keyword args or defaults: foo(bar=None).
460 pass504 pass
461 elif text in BINARY_OPERATORS:505 elif text in BINARY_OPERATORS:
462 need_space = True506 need_space = True
463 elif text in UNARY_OPERATORS:507 elif text in UNARY_OPERATORS:
464 if ((prev_type != tokenize.OP or prev_text in '}])') and not508 # Allow unary operators: -123, -x, +1.
465 (prev_type == tokenize.NAME and iskeyword(prev_text))):509 # Allow argument unpacking: foo(*args, **kwargs).
466 # Allow unary operators: -123, -x, +1.510 if prev_type == tokenize.OP:
467 # Allow argument unpacking: foo(*args, **kwargs).511 if prev_text in '}])':
512 need_space = True
513 elif prev_type == tokenize.NAME:
514 if prev_text not in E225NOT_KEYWORDS:
515 need_space = True
516 else:
468 need_space = True517 need_space = True
469 if need_space and start == prev_end:518 if need_space and start == prev_end:
470 return prev_end, "E225 missing whitespace around operator"519 return prev_end, "E225 missing whitespace around operator"
@@ -513,23 +562,15 @@
513 E251: return magic(r = real, i = imag)562 E251: return magic(r = real, i = imag)
514 """563 """
515 parens = 0564 parens = 0
516 window = ' '565 for match in WHITESPACE_AROUND_NAMED_PARAMETER_REGEX.finditer(
517 equal_ok = ['==', '!=', '<=', '>=']566 logical_line):
518567 text = match.group()
519 for pos, c in enumerate(logical_line):568 if parens and len(text) == 3:
520 window = window[1:] + c569 issue = "E251 no spaces around keyword / parameter equals"
521 if parens:570 return match.start(), issue
522 if window[0] in WHITESPACE and window[1] == '=':571 if text == '(':
523 if window[1:] not in equal_ok:
524 issue = "E251 no spaces around keyword / parameter equals"
525 return pos, issue
526 if window[2] in WHITESPACE and window[1] == '=':
527 if window[:2] not in equal_ok:
528 issue = "E251 no spaces around keyword / parameter equals"
529 return pos, issue
530 if c == '(':
531 parens += 1572 parens += 1
532 elif c == ')':573 elif text == ')':
533 parens -= 1574 parens -= 1
534575
535576
@@ -676,6 +717,18 @@
676##############################################################################717##############################################################################
677718
678719
720if '' == ''.encode():
721 # Python 2: implicit encoding.
722 def readlines(filename):
723 return open(filename).readlines()
724else:
725 # Python 3: decode to latin-1.
726 # This function is lazy, it does not read the encoding declaration.
727 # XXX: use tokenize.detect_encoding()
728 def readlines(filename):
729 return open(filename, encoding='latin-1').readlines()
730
731
679def expand_indent(line):732def expand_indent(line):
680 """733 """
681 Return the amount of indentation.734 Return the amount of indentation.
@@ -765,19 +818,16 @@
765 Load a Python source file, tokenize it, check coding style.818 Load a Python source file, tokenize it, check coding style.
766 """819 """
767820
768 def __init__(self, filename):821 def __init__(self, filename, lines=None):
769 if filename:822 self.filename = filename
770 self.filename = filename823 if filename is None:
771 try:
772 self.lines = open(filename).readlines()
773 except UnicodeDecodeError:
774 # Errors may occur with non-UTF8 files in Python 3000
775 self.lines = open(filename, errors='replace').readlines()
776 else:
777 self.filename = 'stdin'824 self.filename = 'stdin'
778 self.lines = []825 self.lines = lines or []
779 options.counters['physical lines'] = \826 elif lines is None:
780 options.counters.get('physical lines', 0) + len(self.lines)827 self.lines = readlines(filename)
828 else:
829 self.lines = lines
830 options.counters['physical lines'] += len(self.lines)
781831
782 def readline(self):832 def readline(self):
783 """833 """
@@ -830,9 +880,7 @@
830 previous = None880 previous = None
831 for token in self.tokens:881 for token in self.tokens:
832 token_type, text = token[0:2]882 token_type, text = token[0:2]
833 if token_type in (tokenize.COMMENT, tokenize.NL,883 if token_type in SKIP_TOKENS:
834 tokenize.INDENT, tokenize.DEDENT,
835 tokenize.NEWLINE):
836 continue884 continue
837 if token_type == tokenize.STRING:885 if token_type == tokenize.STRING:
838 text = mute_string(text)886 text = mute_string(text)
@@ -840,7 +888,9 @@
840 end_line, end = previous[3]888 end_line, end = previous[3]
841 start_line, start = token[2]889 start_line, start = token[2]
842 if end_line != start_line: # different row890 if end_line != start_line: # different row
843 if self.lines[end_line - 1][end - 1] not in '{[(':891 prev_text = self.lines[end_line - 1][end - 1]
892 if prev_text == ',' or (prev_text not in '{[('
893 and text not in '}])'):
844 logical.append(' ')894 logical.append(' ')
845 length += 1895 length += 1
846 elif end != start: # different column896 elif end != start: # different column
@@ -859,8 +909,7 @@
859 """909 """
860 Build a line from tokens and run all logical checks on it.910 Build a line from tokens and run all logical checks on it.
861 """911 """
862 options.counters['logical lines'] = \912 options.counters['logical lines'] += 1
863 options.counters.get('logical lines', 0) + 1
864 self.build_tokens_line()913 self.build_tokens_line()
865 first_line = self.lines[self.mapping[0][1][2][0] - 1]914 first_line = self.lines[self.mapping[0][1][2][0] - 1]
866 indent = first_line[:self.mapping[0][1][2][1]]915 indent = first_line[:self.mapping[0][1][2][1]]
@@ -869,8 +918,8 @@
869 if options.verbose >= 2:918 if options.verbose >= 2:
870 print(self.logical_line[:80].rstrip())919 print(self.logical_line[:80].rstrip())
871 for name, check, argument_names in options.logical_checks:920 for name, check, argument_names in options.logical_checks:
872 if options.verbose >= 3:921 if options.verbose >= 4:
873 print(' ', name)922 print(' ' + name)
874 result = self.run_check(check, argument_names)923 result = self.run_check(check, argument_names)
875 if result is not None:924 if result is not None:
876 offset, text = result925 offset, text = result
@@ -886,12 +935,14 @@
886 text, check)935 text, check)
887 self.previous_logical = self.logical_line936 self.previous_logical = self.logical_line
888937
889 def check_all(self):938 def check_all(self, expected=None, line_offset=0):
890 """939 """
891 Run all checks on the input file.940 Run all checks on the input file.
892 """941 """
942 self.expected = expected or ()
943 self.line_offset = line_offset
944 self.line_number = 0
893 self.file_errors = 0945 self.file_errors = 0
894 self.line_number = 0
895 self.indent_char = None946 self.indent_char = None
896 self.indent_level = 0947 self.indent_level = 0
897 self.previous_logical = ''948 self.previous_logical = ''
@@ -900,7 +951,13 @@
900 self.tokens = []951 self.tokens = []
901 parens = 0952 parens = 0
902 for token in tokenize.generate_tokens(self.readline_check_physical):953 for token in tokenize.generate_tokens(self.readline_check_physical):
903 # print(tokenize.tok_name[token[0]], repr(token))954 if options.verbose >= 3:
955 if token[2][0] == token[3][0]:
956 pos = '[%s:%s]' % (token[2][1] or '', token[3][1])
957 else:
958 pos = 'l.%s' % token[3][0]
959 print('l.%s\t%s\t%s\t%r' %
960 (token[2][0], pos, tokenize.tok_name[token[0]], token[1]))
904 self.tokens.append(token)961 self.tokens.append(token)
905 token_type, text = token[0:2]962 token_type, text = token[0:2]
906 if token_type == tokenize.OP and text in '([{':963 if token_type == tokenize.OP and text in '([{':
@@ -935,25 +992,24 @@
935 """992 """
936 Report an error, according to options.993 Report an error, according to options.
937 """994 """
995 code = text[:4]
996 if ignore_code(code):
997 return
938 if options.quiet == 1 and not self.file_errors:998 if options.quiet == 1 and not self.file_errors:
939 message(self.filename)999 message(self.filename)
1000 if code in options.counters:
1001 options.counters[code] += 1
1002 else:
1003 options.counters[code] = 1
1004 options.messages[code] = text[5:]
1005 if options.quiet or code in self.expected:
1006 # Don't care about expected errors or warnings
1007 return
940 self.file_errors += 11008 self.file_errors += 1
941 code = text[:4]
942 options.counters[code] = options.counters.get(code, 0) + 1
943 options.messages[code] = text[5:]
944 if options.quiet:
945 return
946 if options.testsuite:
947 basename = os.path.basename(self.filename)
948 if basename[:4] != code:
949 return # Don't care about other errors or warnings
950 if 'not' not in basename:
951 return # Don't print the expected error message
952 if ignore_code(code):
953 return
954 if options.counters[code] == 1 or options.repeat:1009 if options.counters[code] == 1 or options.repeat:
955 message("%s:%s:%d: %s" %1010 message("%s:%s:%d: %s" %
956 (self.filename, line_number, offset + 1, text))1011 (self.filename, self.line_offset + line_number,
1012 offset + 1, text))
957 if options.show_source:1013 if options.show_source:
958 line = self.lines[line_number - 1]1014 line = self.lines[line_number - 1]
959 message(line.rstrip())1015 message(line.rstrip())
@@ -966,43 +1022,33 @@
966 """1022 """
967 Run all checks on a Python source file.1023 Run all checks on a Python source file.
968 """1024 """
969 if excluded(filename):
970 return {}
971 if options.verbose:1025 if options.verbose:
972 message('checking ' + filename)1026 message('checking ' + filename)
973 files_counter_before = options.counters.get('files', 0)
974 if options.testsuite: # Keep showing errors for multiple tests
975 options.counters = {}
976 options.counters['files'] = files_counter_before + 1
977 errors = Checker(filename).check_all()1027 errors = Checker(filename).check_all()
978 if options.testsuite: # Check if the expected error was found1028
979 basename = os.path.basename(filename)1029
980 code = basename[:4]1030def input_dir(dirname, runner=None):
981 count = options.counters.get(code, 0)
982 if count == 0 and 'not' not in basename:
983 message("%s: error %s not found" % (filename, code))
984
985
986def input_dir(dirname):
987 """1031 """
988 Check all Python source files in this directory and all subdirectories.1032 Check all Python source files in this directory and all subdirectories.
989 """1033 """
990 dirname = dirname.rstrip('/')1034 dirname = dirname.rstrip('/')
991 if excluded(dirname):1035 if excluded(dirname):
992 return1036 return
1037 if runner is None:
1038 runner = input_file
993 for root, dirs, files in os.walk(dirname):1039 for root, dirs, files in os.walk(dirname):
994 if options.verbose:1040 if options.verbose:
995 message('directory ' + root)1041 message('directory ' + root)
996 options.counters['directories'] = \1042 options.counters['directories'] += 1
997 options.counters.get('directories', 0) + 1
998 dirs.sort()1043 dirs.sort()
999 for subdir in dirs:1044 for subdir in dirs:
1000 if excluded(subdir):1045 if excluded(subdir):
1001 dirs.remove(subdir)1046 dirs.remove(subdir)
1002 files.sort()1047 files.sort()
1003 for filename in files:1048 for filename in files:
1004 if filename_match(filename):1049 if filename_match(filename) and not excluded(filename):
1005 input_file(os.path.join(root, filename))1050 options.counters['files'] += 1
1051 runner(os.path.join(root, filename))
10061052
10071053
1008def excluded(filename):1054def excluded(filename):
@@ -1041,6 +1087,13 @@
1041 return True1087 return True
10421088
10431089
1090def reset_counters():
1091 for key in list(options.counters.keys()):
1092 if key not in BENCHMARK_KEYS:
1093 del options.counters[key]
1094 options.messages = {}
1095
1096
1044def get_error_statistics():1097def get_error_statistics():
1045 """Get error statistics."""1098 """Get error statistics."""
1046 return get_statistics("E")1099 return get_statistics("E")
@@ -1091,13 +1144,60 @@
1091 Print benchmark numbers.1144 Print benchmark numbers.
1092 """1145 """
1093 print('%-7.2f %s' % (elapsed, 'seconds elapsed'))1146 print('%-7.2f %s' % (elapsed, 'seconds elapsed'))
1094 keys = ['directories', 'files',1147 for key in BENCHMARK_KEYS:
1095 'logical lines', 'physical lines']1148 print('%-7d %s per second (%d total)' % (
1096 for key in keys:1149 options.counters[key] / elapsed, key,
1097 if key in options.counters:1150 options.counters[key]))
1098 print('%-7d %s per second (%d total)' % (1151
1099 options.counters[key] / elapsed, key,1152
1100 options.counters[key]))1153def run_tests(filename):
1154 """
1155 Run all the tests from a file.
1156
1157 A test file can provide many tests. Each test starts with a declaration.
1158 This declaration is a single line starting with '#:'.
1159 It declares codes of expected failures, separated by spaces or 'Okay'
1160 if no failure is expected.
1161 If the file does not contain such declaration, it should pass all tests.
1162 If the declaration is empty, following lines are not checked, until next
1163 declaration.
1164
1165 Examples:
1166
1167 * Only E224 and W701 are expected: #: E224 W701
1168 * Following example is conform: #: Okay
1169 * Don't check these lines: #:
1170 """
1171 lines = readlines(filename) + ['#:\n']
1172 line_offset = 0
1173 codes = ['Okay']
1174 testcase = []
1175 for index, line in enumerate(lines):
1176 if not line.startswith('#:'):
1177 if codes:
1178 # Collect the lines of the test case
1179 testcase.append(line)
1180 continue
1181 if codes and index > 0:
1182 label = '%s:%s:1' % (filename, line_offset + 1)
1183 codes = [c for c in codes if c != 'Okay']
1184 # Run the checker
1185 errors = Checker(filename, testcase).check_all(codes, line_offset)
1186 # Check if the expected errors were found
1187 for code in codes:
1188 if not options.counters.get(code):
1189 errors += 1
1190 message('%s: error %s not found' % (label, code))
1191 if options.verbose and not errors:
1192 message('%s: passed (%s)' % (label, ' '.join(codes)))
1193 # Keep showing errors for multiple tests
1194 reset_counters()
1195 # output the real line numbers
1196 line_offset = index
1197 # configure the expected errors
1198 codes = line.split()[1:]
1199 # empty the test case buffer
1200 del testcase[:]
11011201
11021202
1103def selftest():1203def selftest():
@@ -1120,16 +1220,17 @@
1120 part = part.replace(r'\s', ' ')1220 part = part.replace(r'\s', ' ')
1121 checker.lines.append(part + '\n')1221 checker.lines.append(part + '\n')
1122 options.quiet = 21222 options.quiet = 2
1123 options.counters = {}
1124 checker.check_all()1223 checker.check_all()
1125 error = None1224 error = None
1126 if code == 'Okay':1225 if code == 'Okay':
1127 if len(options.counters) > 1:1226 if len(options.counters) > len(BENCHMARK_KEYS):
1128 codes = [key for key in options.counters.keys()1227 codes = [key for key in options.counters.keys()
1129 if key != 'logical lines']1228 if key not in BENCHMARK_KEYS]
1130 error = "incorrectly found %s" % ', '.join(codes)1229 error = "incorrectly found %s" % ', '.join(codes)
1131 elif options.counters.get(code, 0) == 0:1230 elif not options.counters.get(code):
1132 error = "failed to find %s" % code1231 error = "failed to find %s" % code
1232 # Reset the counters
1233 reset_counters()
1133 if not error:1234 if not error:
1134 count_passed += 11235 count_passed += 1
1135 else:1236 else:
@@ -1193,7 +1294,7 @@
1193 options, args = parser.parse_args(arglist)1294 options, args = parser.parse_args(arglist)
1194 if options.testsuite:1295 if options.testsuite:
1195 args.append(options.testsuite)1296 args.append(options.testsuite)
1196 if len(args) == 0 and not options.doctest:1297 if not args and not options.doctest:
1197 parser.error('input not specified')1298 parser.error('input not specified')
1198 options.prog = os.path.basename(sys.argv[0])1299 options.prog = os.path.basename(sys.argv[0])
1199 options.exclude = options.exclude.split(',')1300 options.exclude = options.exclude.split(',')
@@ -1215,10 +1316,10 @@
1215 options.ignore = []1316 options.ignore = []
1216 else:1317 else:
1217 # The default choice: ignore controversial checks1318 # The default choice: ignore controversial checks
1218 options.ignore = DEFAULT_IGNORE1319 options.ignore = DEFAULT_IGNORE.split(',')
1219 options.physical_checks = find_checks('physical_line')1320 options.physical_checks = find_checks('physical_line')
1220 options.logical_checks = find_checks('logical_line')1321 options.logical_checks = find_checks('logical_line')
1221 options.counters = {}1322 options.counters = dict.fromkeys(BENCHMARK_KEYS, 0)
1222 options.messages = {}1323 options.messages = {}
1223 return options, args1324 return options, args
12241325
@@ -1232,22 +1333,27 @@
1232 import doctest1333 import doctest
1233 doctest.testmod(verbose=options.verbose)1334 doctest.testmod(verbose=options.verbose)
1234 selftest()1335 selftest()
1336 if options.testsuite:
1337 runner = run_tests
1338 else:
1339 runner = input_file
1235 start_time = time.time()1340 start_time = time.time()
1236 for path in args:1341 for path in args:
1237 if os.path.isdir(path):1342 if os.path.isdir(path):
1238 input_dir(path)1343 input_dir(path, runner=runner)
1239 else:1344 elif not excluded(path):
1240 input_file(path)1345 options.counters['files'] += 1
1346 runner(path)
1241 elapsed = time.time() - start_time1347 elapsed = time.time() - start_time
1242 if options.statistics:1348 if options.statistics:
1243 print_statistics()1349 print_statistics()
1244 if options.benchmark:1350 if options.benchmark:
1245 print_benchmark(elapsed)1351 print_benchmark(elapsed)
1246 if options.count:1352 count = get_count()
1247 count = get_count()1353 if count:
1248 if count:1354 if options.count:
1249 sys.stderr.write(str(count) + '\n')1355 sys.stderr.write(str(count) + '\n')
1250 sys.exit(1)1356 sys.exit(1)
12511357
12521358
1253if __name__ == '__main__':1359if __name__ == '__main__':
12541360
=== modified file 'setup.py'
--- setup.py 2010-03-16 19:18:00 +0000
+++ setup.py 2011-08-05 17:38:30 +0000
@@ -1,6 +1,6 @@
1from setuptools import setup, find_packages1from setuptools import setup, find_packages
22
3version = '0.5.0'3version = '0.6.1'
4long_description = '\n\n'.join([open('README.rst').read(),4long_description = '\n\n'.join([open('README.rst').read(),
5 open('CHANGES.txt').read(),5 open('CHANGES.txt').read(),
6 open('TODO.txt').read()])6 open('TODO.txt').read()])

Subscribers

People subscribed via source and target branches

to all changes: