Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1201)

Side by Side Diff: Tools/Scripts/webkitpy/thirdparty/pylint/doc/beginner_pylint_tutorial.txt

Issue 18418010: Check in the thirdparty libs needed for webkitpy. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 ================================================================
2 A Beginner's Guide to Code Standards in Python - Pylint Tutorial
3 ================================================================
4
5 :Author: Robert Kirkpatrick
6
7 For a detailed description of Pylint, see http://www.logilab.org/project/pylint.
8
9
10 Intro
11 -----
12
13 Beginner to coding standards? Pylint can be your guide to reveal what's really
14 going on behind the scenes and help you to become a more aware programmer.
15
16 Sharing code is a rewarding endeavor. Putting your code 'out there' can be
17 either an act of philanthropy, 'coming of age', or a basic extension of belief
18 in open source. Whatever the motivation, your good intentions may not have the
19 desired outcome if people find your code hard to use or understand. The Python
20 community has formalized some recommended programming styles to help everyone
21 write code in a common, agreed-upon style that makes the most sense for shared
22 code. This style is captured in PEP-8_. Pylint can be a quick and easy way of
23 seeing if your code has captured the essence of PEP-8 and is therefore
24 'friendly' to other potential users.
25
26 Perhaps you're not ready to share your code but you'd like to learn a bit more
27 about writing better code and don't know where to start. Pylint can tell you
28 where you may have run astray and point you in the direction to figure out what
29 you have done and how to do better.
30
31 This tutorial is all about approaching coding standards with little or no
32 knowledge of in-depth programming or the code standards themselves. It's the
33 equivalent of skipping the manual and jumping right in.
34
35 My command line prompt for these examples is: ::
36
37 robertk01 Desktop$
38
39 .. _PEP-8: http://www.python.org/dev/peps/pep-0008/
40
41 Getting Started
42 ---------------
43
44 Running Pylint with no arguments will invoke the help dialogue and give you a
45 idea of the arguments available to you. Do that now, i.e.: ::
46
47
48 robertk01 Desktop$ pylint
49 ...
50 a bunch of stuff
51 ...
52
53
54 A couple of the options that we'll focus on here are: ::
55
56 Master:
57 --generate-rcfile=<file>
58 Commands:
59 --help-msg=<msg-id>
60 Commands:
61 --help-msg=<msg-id>
62 Message control:
63 --disable=<msg-ids>
64 Reports:
65 --files-output=<y_or_n>
66 --reports=<y_or_n>
67 --include-ids=<y_or_n>
68 --output-format=<format>
69
70 Also pay attention to the last bit of help output. This gives you a hint of wha t
71 Pylint is going to 'pick on': ::
72
73 Output:
74 Using the default text output, the message format is :
75 MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
76 There are 5 kind of message types :
77 * (C) convention, for programming standard violation
78 * (R) refactor, for bad code smell
79 * (W) warning, for python specific problems
80 * (E) error, for much probably bugs in the code
81 * (F) fatal, if an error occurred which prevented pylint from doing
82 further processing.
83
84 When Pylint is first run on a fresh piece of code, a common complaint is that it
85 is too 'noisy'. The current default configuration is set to enforce all possibl e
86 warnings. We'll use some of the options I noted above to make it suit your
87 preferences a bit better (and thus make it 'scream only when needed').
88
89
90 Your First Pylint'ing
91 ---------------------
92
93 We'll use a basic python script as fodder for our tutorial. I borrowed
94 extensively from the code here: http://www.daniweb.com/code/snippet748.html
95 The starting code we will use is called simplecaeser.py and is here in its
96 entirety: ::
97
98 1 #!/usr/bin/env python
99 2
100 3 import string
101 4
102 5 shift = 3
103 6 choice = raw_input("would you like to encode or decode?")
104 7 word = (raw_input("Please enter text"))
105 8 letters = string.ascii_letters + string.punctuation + string.digits
106 9 encoded = ''
107 10 if choice == "encode":
108 11 for letter in word:
109 12 if letter == ' ':
110 13 encoded = encoded + ' '
111 14 else:
112 15 x = letters.index(letter) + shift
113 16 encoded=encoded + letters[x]
114 17 if choice == "decode":
115 18 for letter in word:
116 19 if letter == ' ':
117 20 encoded = encoded + ' '
118 21 else:
119 22 x = letters.index(letter) - shift
120 23 encoded = encoded + letters[x]
121 24
122 25 print encoded
123
124
125 Let's get started.
126
127 If we run this: ::
128
129 robertk01 Desktop$ pylint simplecaeser.py
130 No config file found, using default configuration
131 ************* Module simplecaeser
132 C: 1: Missing docstring
133 W: 3: Uses of a deprecated module 'string'
134 C: 5: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
135 C: 6: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
136 C: 7: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
137 C: 8: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
138 C: 9: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
139 C: 16: Operator not preceded by a space
140 encoded=encoded + letters[x]
141 ^
142
143
144 Report
145 ======
146 19 statements analysed.
147
148 Duplication
149 -----------
150
151 +-------------------------+------+---------+-----------+
152 | |now |previous |difference |
153 +=========================+======+=========+===========+
154 |nb duplicated lines |0 |0 |= |
155 +-------------------------+------+---------+-----------+
156 |percent duplicated lines |0.000 |0.000 |= |
157 +-------------------------+------+---------+-----------+
158
159
160
161 Raw metrics
162 -----------
163
164 +----------+-------+------+---------+-----------+
165 |type |number |% |previous |difference |
166 +==========+=======+======+=========+===========+
167 |code |21 |87.50 |21 |= |
168 +----------+-------+------+---------+-----------+
169 |docstring |0 |0.00 |0 |= |
170 +----------+-------+------+---------+-----------+
171 |comment |1 |4.17 |1 |= |
172 +----------+-------+------+---------+-----------+
173 |empty |2 |8.33 |2 |= |
174 +----------+-------+------+---------+-----------+
175
176
177
178 Statistics by type
179 ------------------
180
181 +---------+-------+-----------+-----------+------------+---------+
182 |type |number |old number |difference |%documented |%badname |
183 +=========+=======+===========+===========+============+=========+
184 |module |1 |1 |= |0.00 |0.00 |
185 +---------+-------+-----------+-----------+------------+---------+
186 |class |0 |0 |= |0.00 |0.00 |
187 +---------+-------+-----------+-----------+------------+---------+
188 |method |0 |0 |= |0.00 |0.00 |
189 +---------+-------+-----------+-----------+------------+---------+
190 |function |0 |0 |= |0.00 |0.00 |
191 +---------+-------+-----------+-----------+------------+---------+
192
193
194
195 Messages by category
196 --------------------
197
198 +-----------+-------+---------+-----------+
199 |type |number |previous |difference |
200 +===========+=======+=========+===========+
201 |convention |7 |7 |= |
202 +-----------+-------+---------+-----------+
203 |refactor |0 |0 |= |
204 +-----------+-------+---------+-----------+
205 |warning |1 |1 |= |
206 +-----------+-------+---------+-----------+
207 |error |0 |0 |= |
208 +-----------+-------+---------+-----------+
209
210
211
212 Messages
213 --------
214
215 +-----------+-----------+
216 |message id |occurrences |
217 +===========+===========+
218 |C0103 |5 |
219 +-----------+-----------+
220 |W0402 |1 |
221 +-----------+-----------+
222 |C0322 |1 |
223 +-----------+-----------+
224 |C0111 |1 |
225 +-----------+-----------+
226
227
228
229 Global evaluation
230 -----------------
231 Your code has been rated at 5.79/10
232
233
234 Wow. That's a lot of stuff. The first part is the 'messages' section while the
235 second part is the 'report' section. There are two points I want to tackle here .
236
237 First point is that all the tables of statistics (i.e. the report) are a bit
238 overwhelming so I want to silence them. To do that, I will use the "--reports=n " option.
239
240 Second, previous experience taught me that the default output for the messages
241 needed a bit more info. We can see the first line is: ::
242
243 "C: 1: Missing docstring"
244
245 This basically means that line 1 violates a convention 'C'. It's telling me I
246 really should have a docstring. I agree, but what if I didn't fully understand
247 what rule I violated. Knowing only that I violated a convention isn't much help
248 if I'm a newbie. So let's turn on a bit more info by using the option
249 "--include-ids=y".
250
251 .. tip:: Many of Pylint's commonly used command line options have shortcuts.
252 for example, "--reports=n" can be abbreviated to "-r n", and "--include-ids=y"
253 can be abbreviated to "-i y". Pylint's man page lists all these shortcuts.
254
255 Let's do it again! ::
256
257 robertk01 Desktop$ pylint --reports=n --include-ids=y simplecaeser.py
258 No config file found, using default configuration
259 ************* Module simplecaeser
260 C0111: 1: Missing docstring
261 W0402: 3: Uses of a deprecated module 'string'
262 C0103: 5: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
263 C0103: 6: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
264 C0103: 7: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
265 C0103: 8: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$ )
266 C0103: 9: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$ )
267 C0322: 16: Operator not preceded by a space
268 encoded=encoded + letters[x]
269
270 Oooh. I like that better. Now I know that I violated the convention number
271 C0111 and now I can read up a bit more about that. Let's go back to the
272 command line and try this: ::
273
274 robertk01 Desktop$ pylint --help-msg=C0111
275 No config file found, using default configuration
276 :C0111: *Missing docstring*
277 Used when a module, function, class or method has no docstring. Some special
278 methods like __init__ doesn't necessary require a docstring. This message
279 belongs to the basic checker.
280
281 Yeah, ok. That one was a bit of a no-brainer but I have run into error messages
282 that left me with no clue about what went wrong, simply because I was unfamiliar
283 with the underlying mechanism of code theory. One error that puzzled my newbie
284 mind was: ::
285
286 :R0902: *Too many instance attributes (%s/%s)*
287
288 I get it now thanks to Pylint pointing it out to me. If you don't get that one,
289 pour a fresh cup of coffee and look into it - let your programmer mind grow!
290
291
292 The Next Step
293 -------------
294
295 Now that we got some configuration stuff out of the way, let's see what we can
296 do with the remaining warnings.
297
298 If we add a docstring to describe what the code is meant to do that will help.
299 I'm also going to be a bit cowboy and ignore the W0402 message because I like to
300 take risks in life. A deprecation warning means that future versions of Python
301 may not support that code so my code may break in the future. There are 5 C0103
302 messages that we will get to later. Lastly, I violated the convention of using
303 spaces around an operator such as "=" so I'll fix that too. To sum up, I'll add
304 a docstring to line 2, put spaces around the = sign on line 16 and use the
305 "--disable=W0402" to ignore the deprecation warning.
306
307 Here's the updated code: ::
308
309 1 #!/usr/bin/env python
310 2 """This script prompts a user to enter a message to encode or decode
311 3 using a classic Caeser shift substitution (3 letter shift)"""
312 4
313 5 import string
314 6
315 7 shift = 3
316 8 choice = raw_input("would you like to encode or decode?")
317 9 word = (raw_input("Please enter text"))
318 10 letters = string.ascii_letters + string.punctuation + string.digits
319 11 encoded = ''
320 12 if choice == "encode":
321 13 for letter in word:
322 14 if letter == ' ':
323 15 encoded = encoded + ' '
324 16 else:
325 17 x = letters.index(letter) + shift
326 18 encoded = encoded + letters[x]
327 19 if choice == "decode":
328 20 for letter in word:
329 21 if letter == ' ':
330 22 encoded = encoded + ' '
331 23 else:
332 24 x = letters.index(letter) - shift
333 25 encoded = encoded + letters[x]
334 26
335 27 print encoded
336
337 And here's what happens when we run it with our --disable=W0402 option: ::
338
339 robertk01 Desktop$ pylint --reports=n --include-ids=y --disable=W0402 simpleca eser.py
340 No config file found, using default configuration
341 ************* Module simplecaeser
342 C0103: 7: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
343 C0103: 8: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
344 C0103: 9: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
345 C0103: 10: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$ )
346 C0103: 11: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$ )
347
348 Nice! We're down to just the C0103 messages.
349
350 There are fairly well defined conventions around naming things like instance
351 variables, functions, classes, etc. The conventions focus on the use of
352 UPPERCASE and lowercase as well as the characters that separate multiple words
353 in the name. This lends itself well to checking via a regular expression, thus
354 the "should match (([A-Z\_][A-Z1-9\_]*)|(__.*__))$".
355
356 In this case Pylint is telling me that those variables appear to be constants
357 and should be all UPPERCASE. This rule is in fact a naming convention that is
358 specific to the folks at Logilab who created Pylint. That is the way they have
359 chosen to name those variables. You too can create your own in-house naming
360 conventions but for the purpose of this tutorial, we want to stick to the PEP-8
361 standard. In this case, the variables I declared should follow the convention
362 of all lowercase. The appropriate rule would be something like:
363 "should match [a-z\_][a-z0-9\_]{2,30}$". Notice the lowercase letters in the
364 regular expression (a-z versus A-Z).
365
366 If we run that rule using a --const-rgx='[a-z\_][a-z0-9\_]{2,30}$' option, it
367 will now be quite quiet: ::
368
369 robertk01 Desktop$ pylint --reports=n --include-ids=y --disable=W0402 --const- rgx='[a-z_][a-z0-9_]{2,30}$' simplecaeser.py
370 No config file found, using default configuration
371
372 Regular expressions can be quite a beast so take my word on this particular
373 example but go ahead and `read up`_ on them if you want.
374
375 .. tip::
376 It would really be a pain in the butt to have to use all these options
377 on the command line all the time. That's what the rc file is for. We can
378 configure our Pylint to store our options for us so we don't have to declare
379 them on the command line. Using the rc file is a nice way of formalizing your
380 rules and quickly sharing them with others. Invoking 'pylint
381 --generate-rcfile' will create a sample rcfile with all the options set and
382 explained in comments.
383
384 That's it for the basic intro. More tutorials will follow.
385
386 .. _`read up`: http://docs.python.org/library/re.html
OLDNEW
« no previous file with comments | « Tools/Scripts/webkitpy/thirdparty/pylint/doc/FAQ.txt ('k') | Tools/Scripts/webkitpy/thirdparty/pylint/doc/features.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698