| Index: Tools/Scripts/webkitpy/thirdparty/pylint/doc/beginner_pylint_tutorial.txt
|
| diff --git a/Tools/Scripts/webkitpy/thirdparty/pylint/doc/beginner_pylint_tutorial.txt b/Tools/Scripts/webkitpy/thirdparty/pylint/doc/beginner_pylint_tutorial.txt
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ed0e0ac5e4b4744c72b33c653ce963004ba04942
|
| --- /dev/null
|
| +++ b/Tools/Scripts/webkitpy/thirdparty/pylint/doc/beginner_pylint_tutorial.txt
|
| @@ -0,0 +1,386 @@
|
| +================================================================
|
| +A Beginner's Guide to Code Standards in Python - Pylint Tutorial
|
| +================================================================
|
| +
|
| +:Author: Robert Kirkpatrick
|
| +
|
| +For a detailed description of Pylint, see http://www.logilab.org/project/pylint.
|
| +
|
| +
|
| +Intro
|
| +-----
|
| +
|
| +Beginner to coding standards? Pylint can be your guide to reveal what's really
|
| +going on behind the scenes and help you to become a more aware programmer.
|
| +
|
| +Sharing code is a rewarding endeavor. Putting your code 'out there' can be
|
| +either an act of philanthropy, 'coming of age', or a basic extension of belief
|
| +in open source. Whatever the motivation, your good intentions may not have the
|
| +desired outcome if people find your code hard to use or understand. The Python
|
| +community has formalized some recommended programming styles to help everyone
|
| +write code in a common, agreed-upon style that makes the most sense for shared
|
| +code. This style is captured in PEP-8_. Pylint can be a quick and easy way of
|
| +seeing if your code has captured the essence of PEP-8 and is therefore
|
| +'friendly' to other potential users.
|
| +
|
| +Perhaps you're not ready to share your code but you'd like to learn a bit more
|
| +about writing better code and don't know where to start. Pylint can tell you
|
| +where you may have run astray and point you in the direction to figure out what
|
| +you have done and how to do better.
|
| +
|
| +This tutorial is all about approaching coding standards with little or no
|
| +knowledge of in-depth programming or the code standards themselves. It's the
|
| +equivalent of skipping the manual and jumping right in.
|
| +
|
| +My command line prompt for these examples is: ::
|
| +
|
| + robertk01 Desktop$
|
| +
|
| +.. _PEP-8: http://www.python.org/dev/peps/pep-0008/
|
| +
|
| +Getting Started
|
| +---------------
|
| +
|
| +Running Pylint with no arguments will invoke the help dialogue and give you a
|
| +idea of the arguments available to you. Do that now, i.e.: ::
|
| +
|
| +
|
| + robertk01 Desktop$ pylint
|
| + ...
|
| + a bunch of stuff
|
| + ...
|
| +
|
| +
|
| +A couple of the options that we'll focus on here are: ::
|
| +
|
| + Master:
|
| + --generate-rcfile=<file>
|
| + Commands:
|
| + --help-msg=<msg-id>
|
| + Commands:
|
| + --help-msg=<msg-id>
|
| + Message control:
|
| + --disable=<msg-ids>
|
| + Reports:
|
| + --files-output=<y_or_n>
|
| + --reports=<y_or_n>
|
| + --include-ids=<y_or_n>
|
| + --output-format=<format>
|
| +
|
| +Also pay attention to the last bit of help output. This gives you a hint of what
|
| +Pylint is going to 'pick on': ::
|
| +
|
| + Output:
|
| + Using the default text output, the message format is :
|
| + MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
|
| + There are 5 kind of message types :
|
| + * (C) convention, for programming standard violation
|
| + * (R) refactor, for bad code smell
|
| + * (W) warning, for python specific problems
|
| + * (E) error, for much probably bugs in the code
|
| + * (F) fatal, if an error occurred which prevented pylint from doing
|
| + further processing.
|
| +
|
| +When Pylint is first run on a fresh piece of code, a common complaint is that it
|
| +is too 'noisy'. The current default configuration is set to enforce all possible
|
| +warnings. We'll use some of the options I noted above to make it suit your
|
| +preferences a bit better (and thus make it 'scream only when needed').
|
| +
|
| +
|
| +Your First Pylint'ing
|
| +---------------------
|
| +
|
| +We'll use a basic python script as fodder for our tutorial. I borrowed
|
| +extensively from the code here: http://www.daniweb.com/code/snippet748.html
|
| +The starting code we will use is called simplecaeser.py and is here in its
|
| +entirety: ::
|
| +
|
| + 1 #!/usr/bin/env python
|
| + 2
|
| + 3 import string
|
| + 4
|
| + 5 shift = 3
|
| + 6 choice = raw_input("would you like to encode or decode?")
|
| + 7 word = (raw_input("Please enter text"))
|
| + 8 letters = string.ascii_letters + string.punctuation + string.digits
|
| + 9 encoded = ''
|
| + 10 if choice == "encode":
|
| + 11 for letter in word:
|
| + 12 if letter == ' ':
|
| + 13 encoded = encoded + ' '
|
| + 14 else:
|
| + 15 x = letters.index(letter) + shift
|
| + 16 encoded=encoded + letters[x]
|
| + 17 if choice == "decode":
|
| + 18 for letter in word:
|
| + 19 if letter == ' ':
|
| + 20 encoded = encoded + ' '
|
| + 21 else:
|
| + 22 x = letters.index(letter) - shift
|
| + 23 encoded = encoded + letters[x]
|
| + 24
|
| + 25 print encoded
|
| +
|
| +
|
| +Let's get started.
|
| +
|
| +If we run this: ::
|
| +
|
| + robertk01 Desktop$ pylint simplecaeser.py
|
| + No config file found, using default configuration
|
| + ************* Module simplecaeser
|
| + C: 1: Missing docstring
|
| + W: 3: Uses of a deprecated module 'string'
|
| + C: 5: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C: 6: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C: 7: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C: 8: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C: 9: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C: 16: Operator not preceded by a space
|
| + encoded=encoded + letters[x]
|
| + ^
|
| +
|
| +
|
| + Report
|
| + ======
|
| + 19 statements analysed.
|
| +
|
| + Duplication
|
| + -----------
|
| +
|
| + +-------------------------+------+---------+-----------+
|
| + | |now |previous |difference |
|
| + +=========================+======+=========+===========+
|
| + |nb duplicated lines |0 |0 |= |
|
| + +-------------------------+------+---------+-----------+
|
| + |percent duplicated lines |0.000 |0.000 |= |
|
| + +-------------------------+------+---------+-----------+
|
| +
|
| +
|
| +
|
| + Raw metrics
|
| + -----------
|
| +
|
| + +----------+-------+------+---------+-----------+
|
| + |type |number |% |previous |difference |
|
| + +==========+=======+======+=========+===========+
|
| + |code |21 |87.50 |21 |= |
|
| + +----------+-------+------+---------+-----------+
|
| + |docstring |0 |0.00 |0 |= |
|
| + +----------+-------+------+---------+-----------+
|
| + |comment |1 |4.17 |1 |= |
|
| + +----------+-------+------+---------+-----------+
|
| + |empty |2 |8.33 |2 |= |
|
| + +----------+-------+------+---------+-----------+
|
| +
|
| +
|
| +
|
| + Statistics by type
|
| + ------------------
|
| +
|
| + +---------+-------+-----------+-----------+------------+---------+
|
| + |type |number |old number |difference |%documented |%badname |
|
| + +=========+=======+===========+===========+============+=========+
|
| + |module |1 |1 |= |0.00 |0.00 |
|
| + +---------+-------+-----------+-----------+------------+---------+
|
| + |class |0 |0 |= |0.00 |0.00 |
|
| + +---------+-------+-----------+-----------+------------+---------+
|
| + |method |0 |0 |= |0.00 |0.00 |
|
| + +---------+-------+-----------+-----------+------------+---------+
|
| + |function |0 |0 |= |0.00 |0.00 |
|
| + +---------+-------+-----------+-----------+------------+---------+
|
| +
|
| +
|
| +
|
| + Messages by category
|
| + --------------------
|
| +
|
| + +-----------+-------+---------+-----------+
|
| + |type |number |previous |difference |
|
| + +===========+=======+=========+===========+
|
| + |convention |7 |7 |= |
|
| + +-----------+-------+---------+-----------+
|
| + |refactor |0 |0 |= |
|
| + +-----------+-------+---------+-----------+
|
| + |warning |1 |1 |= |
|
| + +-----------+-------+---------+-----------+
|
| + |error |0 |0 |= |
|
| + +-----------+-------+---------+-----------+
|
| +
|
| +
|
| +
|
| + Messages
|
| + --------
|
| +
|
| + +-----------+-----------+
|
| + |message id |occurrences |
|
| + +===========+===========+
|
| + |C0103 |5 |
|
| + +-----------+-----------+
|
| + |W0402 |1 |
|
| + +-----------+-----------+
|
| + |C0322 |1 |
|
| + +-----------+-----------+
|
| + |C0111 |1 |
|
| + +-----------+-----------+
|
| +
|
| +
|
| +
|
| + Global evaluation
|
| + -----------------
|
| + Your code has been rated at 5.79/10
|
| +
|
| +
|
| +Wow. That's a lot of stuff. The first part is the 'messages' section while the
|
| +second part is the 'report' section. There are two points I want to tackle here.
|
| +
|
| +First point is that all the tables of statistics (i.e. the report) are a bit
|
| +overwhelming so I want to silence them. To do that, I will use the "--reports=n" option.
|
| +
|
| +Second, previous experience taught me that the default output for the messages
|
| +needed a bit more info. We can see the first line is: ::
|
| +
|
| + "C: 1: Missing docstring"
|
| +
|
| +This basically means that line 1 violates a convention 'C'. It's telling me I
|
| +really should have a docstring. I agree, but what if I didn't fully understand
|
| +what rule I violated. Knowing only that I violated a convention isn't much help
|
| +if I'm a newbie. So let's turn on a bit more info by using the option
|
| +"--include-ids=y".
|
| +
|
| +.. tip:: Many of Pylint's commonly used command line options have shortcuts.
|
| + for example, "--reports=n" can be abbreviated to "-r n", and "--include-ids=y"
|
| + can be abbreviated to "-i y". Pylint's man page lists all these shortcuts.
|
| +
|
| +Let's do it again! ::
|
| +
|
| + robertk01 Desktop$ pylint --reports=n --include-ids=y simplecaeser.py
|
| + No config file found, using default configuration
|
| + ************* Module simplecaeser
|
| + C0111: 1: Missing docstring
|
| + W0402: 3: Uses of a deprecated module 'string'
|
| + C0103: 5: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 6: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 7: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 8: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 9: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0322: 16: Operator not preceded by a space
|
| + encoded=encoded + letters[x]
|
| +
|
| +Oooh. I like that better. Now I know that I violated the convention number
|
| +C0111 and now I can read up a bit more about that. Let's go back to the
|
| +command line and try this: ::
|
| +
|
| + robertk01 Desktop$ pylint --help-msg=C0111
|
| + No config file found, using default configuration
|
| + :C0111: *Missing docstring*
|
| + Used when a module, function, class or method has no docstring. Some special
|
| + methods like __init__ doesn't necessary require a docstring. This message
|
| + belongs to the basic checker.
|
| +
|
| +Yeah, ok. That one was a bit of a no-brainer but I have run into error messages
|
| +that left me with no clue about what went wrong, simply because I was unfamiliar
|
| +with the underlying mechanism of code theory. One error that puzzled my newbie
|
| +mind was: ::
|
| +
|
| + :R0902: *Too many instance attributes (%s/%s)*
|
| +
|
| +I get it now thanks to Pylint pointing it out to me. If you don't get that one,
|
| +pour a fresh cup of coffee and look into it - let your programmer mind grow!
|
| +
|
| +
|
| +The Next Step
|
| +-------------
|
| +
|
| +Now that we got some configuration stuff out of the way, let's see what we can
|
| +do with the remaining warnings.
|
| +
|
| +If we add a docstring to describe what the code is meant to do that will help.
|
| +I'm also going to be a bit cowboy and ignore the W0402 message because I like to
|
| +take risks in life. A deprecation warning means that future versions of Python
|
| +may not support that code so my code may break in the future. There are 5 C0103
|
| +messages that we will get to later. Lastly, I violated the convention of using
|
| +spaces around an operator such as "=" so I'll fix that too. To sum up, I'll add
|
| +a docstring to line 2, put spaces around the = sign on line 16 and use the
|
| +"--disable=W0402" to ignore the deprecation warning.
|
| +
|
| +Here's the updated code: ::
|
| +
|
| + 1 #!/usr/bin/env python
|
| + 2 """This script prompts a user to enter a message to encode or decode
|
| + 3 using a classic Caeser shift substitution (3 letter shift)"""
|
| + 4
|
| + 5 import string
|
| + 6
|
| + 7 shift = 3
|
| + 8 choice = raw_input("would you like to encode or decode?")
|
| + 9 word = (raw_input("Please enter text"))
|
| + 10 letters = string.ascii_letters + string.punctuation + string.digits
|
| + 11 encoded = ''
|
| + 12 if choice == "encode":
|
| + 13 for letter in word:
|
| + 14 if letter == ' ':
|
| + 15 encoded = encoded + ' '
|
| + 16 else:
|
| + 17 x = letters.index(letter) + shift
|
| + 18 encoded = encoded + letters[x]
|
| + 19 if choice == "decode":
|
| + 20 for letter in word:
|
| + 21 if letter == ' ':
|
| + 22 encoded = encoded + ' '
|
| + 23 else:
|
| + 24 x = letters.index(letter) - shift
|
| + 25 encoded = encoded + letters[x]
|
| + 26
|
| + 27 print encoded
|
| +
|
| +And here's what happens when we run it with our --disable=W0402 option: ::
|
| +
|
| + robertk01 Desktop$ pylint --reports=n --include-ids=y --disable=W0402 simplecaeser.py
|
| + No config file found, using default configuration
|
| + ************* Module simplecaeser
|
| + C0103: 7: Invalid name "shift" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 8: Invalid name "choice" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 9: Invalid name "word" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 10: Invalid name "letters" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| + C0103: 11: Invalid name "encoded" (should match (([A-Z_][A-Z1-9_]*)|(__.*__))$)
|
| +
|
| +Nice! We're down to just the C0103 messages.
|
| +
|
| +There are fairly well defined conventions around naming things like instance
|
| +variables, functions, classes, etc. The conventions focus on the use of
|
| +UPPERCASE and lowercase as well as the characters that separate multiple words
|
| +in the name. This lends itself well to checking via a regular expression, thus
|
| +the "should match (([A-Z\_][A-Z1-9\_]*)|(__.*__))$".
|
| +
|
| +In this case Pylint is telling me that those variables appear to be constants
|
| +and should be all UPPERCASE. This rule is in fact a naming convention that is
|
| +specific to the folks at Logilab who created Pylint. That is the way they have
|
| +chosen to name those variables. You too can create your own in-house naming
|
| +conventions but for the purpose of this tutorial, we want to stick to the PEP-8
|
| +standard. In this case, the variables I declared should follow the convention
|
| +of all lowercase. The appropriate rule would be something like:
|
| +"should match [a-z\_][a-z0-9\_]{2,30}$". Notice the lowercase letters in the
|
| +regular expression (a-z versus A-Z).
|
| +
|
| +If we run that rule using a --const-rgx='[a-z\_][a-z0-9\_]{2,30}$' option, it
|
| +will now be quite quiet: ::
|
| +
|
| + robertk01 Desktop$ pylint --reports=n --include-ids=y --disable=W0402 --const-rgx='[a-z_][a-z0-9_]{2,30}$' simplecaeser.py
|
| + No config file found, using default configuration
|
| +
|
| +Regular expressions can be quite a beast so take my word on this particular
|
| +example but go ahead and `read up`_ on them if you want.
|
| +
|
| +.. tip::
|
| + It would really be a pain in the butt to have to use all these options
|
| + on the command line all the time. That's what the rc file is for. We can
|
| + configure our Pylint to store our options for us so we don't have to declare
|
| + them on the command line. Using the rc file is a nice way of formalizing your
|
| + rules and quickly sharing them with others. Invoking 'pylint
|
| + --generate-rcfile' will create a sample rcfile with all the options set and
|
| + explained in comments.
|
| +
|
| +That's it for the basic intro. More tutorials will follow.
|
| +
|
| +.. _`read up`: http://docs.python.org/library/re.html
|
|
|