Merge lp:~adiroiban/pocket-lint/pep-options into lp:pocket-lint

Proposed by Adi Roiban
Status: Merged
Merged at revision: 447
Proposed branch: lp:~adiroiban/pocket-lint/pep-options
Merge into: lp:pocket-lint
Diff against target: 302 lines (+113/-52)
4 files modified
NEWS (+7/-0)
pocketlint/formatcheck.py (+57/-36)
pocketlint/tests/test_javascript.py (+37/-16)
pocketlint/tests/test_python.py (+12/-0)
To merge this branch: bzr merge lp:~adiroiban/pocket-lint/pep-options
Reviewer Review Type Date Requested Status
Curtis Hovey code Approve
Review via email: mp+204911@code.launchpad.net

Description of the change

Description
-----------

PEP8 has now at least one controversion option... but users might want to ignore some pep8 messages.

Changes
-------

I have created a dedicated (more complex) object to hold all pocket-lint options.
It can extend the command line options.

The current code was done to minimize changes and provide backward compatibility.

I have done a refactored the UniversalChecker to use the init from BaseClass.

I have also updated the NEWS file. I find it easier to check latest changes in a single file, rather than look into VC history.

Test
----

I have run the tests on py2.7 ... looking forward for travis-ci integration to land on master and then we can see a neutral results on both 2.7 and 3.3

Please review the changes.

Thanks!

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you.

I reconciled some changes/tests with the previous branches I just merged. I am going to extend PocketLintOptions
in a moment to support PEP8's options.hang_closing so that I can stop contradicting python's rule that continuations
are indented.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-07-02 19:16:39 +0000
3+++ NEWS 2014-02-05 13:36:41 +0000
4@@ -1,3 +1,10 @@
5+pocket-lint-0.5.0: No Release Date
6+==================================
7+
8+ * Add support for setting pep8 options using the new PocketLintOptions.
9+ * By default disable closure-linter.
10+
11+
12 pocket-lint-0.3: The first release
13 ==================================
14
15
16=== modified file 'pocketlint/formatcheck.py'
17--- pocketlint/formatcheck.py 2013-11-06 15:21:20 +0000
18+++ pocketlint/formatcheck.py 2014-02-05 13:36:41 +0000
19@@ -254,6 +254,41 @@
20 return Language.get_language(file_path) is not None
21
22
23+class PocketLintOptions(object):
24+ """Default options used by pocketlint"""
25+
26+ def __init__(self, command_options=None):
27+ self.max_line_length = 0
28+
29+ self.jslint = {
30+ 'enabled': True,
31+ }
32+
33+ self.closure_linter = {
34+ # Disabled by default, since jslint is the default linter.
35+ 'enabled': False,
36+ # List of Google Closure Errors to ignore.
37+ # Ex 110 is line to long which is already provided by pocket-lint.
38+ 'ignore': [110],
39+ }
40+
41+ # See pep8.StyleGuide for available options.
42+ self.pep8 = {
43+ 'max_line_length': pep8.MAX_LINE_LENGTH,
44+ }
45+
46+ if command_options:
47+ self._updateFromCommandLineOptions(command_options)
48+
49+ def _updateFromCommandLineOptions(self, options):
50+ """
51+ Update with options received from command line.
52+ """
53+ # Update maximum line length.
54+ self.max_line_length = options.max_line_length
55+ self.pep8['max_line_length'] = options.max_line_length - 1
56+
57+
58 class BaseChecker(object):
59 """Common rules for checkers.
60
61@@ -269,7 +304,13 @@
62 if self.REENCODE:
63 self.text = u(text)
64 self.set_reporter(reporter=reporter)
65- self.options = options
66+
67+ if options is None:
68+ self.options = PocketLintOptions()
69+ elif not isinstance(options, PocketLintOptions):
70+ self.options = PocketLintOptions(command_options=options)
71+ else:
72+ self.options = options
73
74 def set_reporter(self, reporter=None):
75 """Set the reporter for messages."""
76@@ -295,7 +336,7 @@
77 @property
78 def check_length_filter(self):
79 '''Default filter used by default for checking line length.'''
80- if self.options:
81+ if self.options.max_line_length:
82 return self.options.max_line_length
83 else:
84 return DEFAULT_MAX_LENGTH
85@@ -306,13 +347,13 @@
86
87 def __init__(self, file_path, text,
88 language=None, reporter=None, options=None):
89- self.file_path = file_path
90- self.base_dir = os.path.dirname(file_path)
91- self.file_name = os.path.basename(file_path)
92- self.text = text
93- self.set_reporter(reporter=reporter)
94+ super(UniversalChecker, self).__init__(
95+ file_path=file_path,
96+ text=text,
97+ reporter=reporter,
98+ options=options,
99+ )
100 self.language = language
101- self.options = options
102 self.file_lines_view = None
103
104 def check(self):
105@@ -649,8 +690,7 @@
106
107 def check_pep8(self):
108 """Check style."""
109- style_options = pep8.StyleGuide(
110- max_line_length=self.check_length_filter)
111+ style_options = pep8.StyleGuide(**self.options.pep8)
112 options = style_options.options
113 pep8_report = PEP8Report(options, self.message)
114 try:
115@@ -687,7 +727,7 @@
116 @property
117 def check_length_filter(self):
118 # The pep8 lib counts from 0.
119- if self.options:
120+ if self.options.max_line_length:
121 return self.options.max_line_length - 1
122 else:
123 return pep8.MAX_LINE_LENGTH
124@@ -711,20 +751,16 @@
125 FULLJSLINT = os.path.join(HERE, 'contrib/fulljslint.js')
126 JSREPORTER = os.path.join(HERE, 'jsreporter.js')
127
128- # List of Google Closure Errors to ignore.
129- # Ex 110 is line to long which is already provided by pocket-lint.
130- GOOGLE_CLOSURE_IGNORE = [110]
131-
132 def check(self):
133 """Check the syntax of the JavaScript code."""
134 self.check_jslint()
135- self.check_google_closure()
136+ self.check_closure_linter()
137 self.check_text()
138 self.check_windows_endlines()
139
140 def check_jslint(self):
141 """Check file using jslint."""
142- if JS is None or self.text == '':
143+ if JS is None or self.text == '' or not self.options.jslint['enabled']:
144 return
145 args = [JS, self.JSREPORTER, self.FULLJSLINT, self.file_path]
146 jslint = subprocess.Popen(
147@@ -738,9 +774,9 @@
148 line_no -= 1
149 self.message(line_no, message, icon='error')
150
151- def check_google_closure(self):
152+ def check_closure_linter(self):
153 """Check file using Google Closure Linter."""
154- if not closure_linter:
155+ if not self.options.closure_linter['enabled']:
156 return
157
158 from closure_linter import runner
159@@ -749,28 +785,13 @@
160 error_handler = erroraccumulator.ErrorAccumulator()
161 runner.Run(self.file_path, error_handler)
162 for error in error_handler.GetErrors():
163- if error.code in self.google_closure_ignore:
164+ if error.code in self.options.closure_linter['ignore']:
165 continue
166 # Use a similar format as default Google Closure Linter formatter.
167 # Line 12, E:0010: Missing semicolon at end of line
168 message = 'E:%04d: %s' % (error.code, error.message)
169 self.message(error.token.line_number, message, icon='error')
170
171- @property
172- def google_closure_ignore(self):
173- """
174- Return the list of ignored errors for Google Closure Linter.
175-
176- Return either the default list or the list specified as options.
177- """
178- if not self.options:
179- return self.GOOGLE_CLOSURE_IGNORE
180- ignore_list = getattr(self.options, 'google_closure_ignore', None)
181- if ignore_list is None:
182- return self.GOOGLE_CLOSURE_IGNORE
183- else:
184- return ignore_list
185-
186 def check_debugger(self, line_no, line):
187 """Check the length of the line."""
188 debugger_call = 'debugger;'
189@@ -1063,7 +1084,7 @@
190 @property
191 def check_length_filter(self):
192 # Go land standards don't have a max length; it suggests common sense.
193- if self.options:
194+ if self.options.max_line_length:
195 return self.options.max_line_length - 1
196 else:
197 return 160
198
199=== modified file 'pocketlint/tests/test_javascript.py'
200--- pocketlint/tests/test_javascript.py 2013-10-09 12:22:58 +0000
201+++ pocketlint/tests/test_javascript.py 2014-02-05 13:36:41 +0000
202@@ -14,7 +14,7 @@
203 JavascriptChecker,
204 JS
205 )
206-from pocketlint.tests import Bunch, CheckerTestCase
207+from pocketlint.tests import CheckerTestCase
208 from pocketlint.tests.test_text import TestAnyTextMixin
209
210 try:
211@@ -61,14 +61,21 @@
212 [(1, "Expected ';' and instead saw '(end)'.")],
213 self.reporter.messages)
214
215- def test_google_closure(self):
216+ closure_linter_trigger = (
217+ 'var test = 1+ 1;\n'
218+ )
219+
220+ def test_closure_linter(self):
221 if closure_linter is None:
222 raise unittest.SkipTest('Google Closure Linter not available.')
223- google_closure_trigger = (
224- 'var test = 1+ 1;\n'
225- )
226- self.write_to_file(self.file, google_closure_trigger)
227- checker = JavascriptChecker(self.file.name, invalid_js, self.reporter)
228+
229+ self.write_to_file(self.file, self.closure_linter_trigger)
230+ checker = JavascriptChecker(
231+ self.file.name, invalid_js, self.reporter)
232+ checker.options.closure_linter.update({
233+ 'enabled': True,
234+ 'ignore': [],
235+ })
236
237 checker.check()
238
239@@ -76,17 +83,31 @@
240 [(1, u'E:0002: Missing space before "+"')],
241 self.reporter.messages)
242
243- def test_google_closure_ignore(self):
244+ def test_closure_linter_ignore(self):
245 if closure_linter is None:
246 raise unittest.SkipTest('Google Closure Linter not available.')
247- google_closure_trigger = (
248- 'var test = 1+ 1;\n'
249- )
250- self.write_to_file(self.file, google_closure_trigger)
251- options = Bunch(
252- google_closure_ignore=[2], max_line_length=80)
253- checker = JavascriptChecker(
254- self.file.name, invalid_js, self.reporter, options)
255+
256+ self.write_to_file(self.file, self.closure_linter_trigger)
257+ checker = JavascriptChecker(
258+ self.file.name, invalid_js, self.reporter)
259+ checker.options.closure_linter.update({
260+ 'enabled': True,
261+ 'ignore': [2],
262+ })
263+
264+ checker.check()
265+
266+ self.assertEqual([], self.reporter.messages)
267+
268+ def test_closure_linter_disabled(self):
269+ """No errors are reported when closure linter is disabled."""
270+ self.write_to_file(self.file, self.closure_linter_trigger)
271+ checker = JavascriptChecker(
272+ self.file.name, invalid_js, self.reporter)
273+ checker.options.closure_linter.update({
274+ 'enabled': False,
275+ 'ignore': [],
276+ })
277
278 checker.check()
279
280
281=== modified file 'pocketlint/tests/test_python.py'
282--- pocketlint/tests/test_python.py 2013-02-16 18:03:51 +0000
283+++ pocketlint/tests/test_python.py 2014-02-05 13:36:41 +0000
284@@ -232,6 +232,18 @@
285 [(1, 'E501 line too long (70 > 59 characters)')],
286 self.reporter.messages)
287
288+ def test_pep8_options(self):
289+ """It can set PEP8 options."""
290+ long_line = '1234 56189' * 7 + '\n'
291+ self.write_to_file(self.file, long_line)
292+ checker = PythonChecker(self.file.name, long_line, self.reporter)
293+ checker.options.pep8['ignore'] = ['E501']
294+ checker.options.pep8['max_line_length'] = 60
295+
296+ checker.check_pep8()
297+
298+ self.assertEqual([], self.reporter.messages)
299+
300
301 class TestText(CheckerTestCase, TestAnyTextMixin):
302 """Verify text integration."""

Subscribers

People subscribed via source and target branches

to all changes: