Skip to content

Commit 35579eb

Browse files
[doc] Less personal style for the tutorial (#7719)
There's a lot of contributor in pylint and we generally do not talk about ourselves in the documentation except in release notes.
1 parent 160345d commit 35579eb

File tree

1 file changed

+116
-156
lines changed

1 file changed

+116
-156
lines changed

doc/tutorial.rst

Lines changed: 116 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,27 @@
44
Tutorial
55
========
66

7-
:Author: Robert Kirkpatrick
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`_, the "Style Guide for Python Code".
23-
Pylint can be a quick and easy way of
24-
seeing if your code has captured the essence of `PEP 8`_ and is therefore
25-
``friendly`` to other potential users.
26-
27-
Perhaps you're not ready to share your code but you'd like to learn a bit more
28-
about writing better code and don't know where to start. Pylint can tell you
29-
where you may have run astray and point you in the direction to figure out what
30-
you have done and how to do better.
31-
327
This tutorial is all about approaching coding standards with little or no
338
knowledge of in-depth programming or the code standards themselves. It's the
349
equivalent of skipping the manual and jumping right in.
3510

36-
My command line prompt for these examples is:
11+
The command line prompt for these examples is:
3712

3813
.. sourcecode:: console
3914

40-
robertk01 Desktop$
15+
tutor Desktop$
4116

4217
.. _PEP 8: https://peps.python.org/pep-0008/
4318

4419
Getting Started
4520
---------------
4621

47-
Running Pylint with no arguments will invoke the help dialogue and give you an
48-
idea of the arguments available to you. Do that now, i.e.:
22+
Running Pylint with the ``--help`` arguments will give you an idea of the arguments
23+
available. Do that now, i.e.:
4924

5025
.. sourcecode:: console
5126

52-
robertk01 Desktop$ pylint
53-
...
54-
a bunch of stuff
55-
...
27+
pylint --help
5628

5729

5830
A couple of the options that we'll focus on here are: ::
@@ -66,17 +38,12 @@ A couple of the options that we'll focus on here are: ::
6638
--reports=<y or n>
6739
--output-format=<format>
6840

69-
If you need more detail, you can also ask for an even longer help message,
70-
like so: ::
41+
If you need more detail, you can also ask for an even longer help message: ::
7142

72-
robertk01 Desktop$ pylint --long-help
73-
...
74-
Even more stuff
75-
...
43+
pylint --long-help
7644

77-
Pay attention to the last bit of this longer help output. This gives you a
78-
hint of what
79-
Pylint is going to ``pick on``: ::
45+
Pay attention to the last bit of this longer help output. This gives you a
46+
hint of what Pylint is going to ``pick on``: ::
8047

8148
Output:
8249
Using the default text output, the message format is :
@@ -90,167 +57,160 @@ Pylint is going to ``pick on``: ::
9057
further processing.
9158

9259
When Pylint is first run on a fresh piece of code, a common complaint is that it
93-
is too ``noisy``. The current default configuration is set to enforce all possible
94-
warnings. We'll use some of the options I noted above to make it suit your
95-
preferences a bit better (and thus make it emit messages only when needed).
96-
60+
is too ``noisy``. The default configuration enforce a lot of warnings.
61+
We'll use some of the options we noted above to make it suit your
62+
preferences a bit better.
9763

9864
Your First Pylint'ing
9965
---------------------
10066

101-
We'll use a basic Python script as fodder for our tutorial.
102-
The starting code we will use is called simplecaesar.py and is here in its
103-
entirety:
67+
We'll use a basic Python script with ``black`` already applied on it,
68+
as fodder for our tutorial. The starting code we will use is called
69+
``simplecaesar.py`` and is here in its entirety:
10470

10571
.. sourcecode:: python
10672

107-
#!/usr/bin/env python3
108-
109-
import string;
73+
#!/usr/bin/env python3
11074

111-
shift = 3
112-
choice = input("would you like to encode or decode?")
113-
word = input("Please enter text")
114-
letters = string.ascii_letters + string.punctuation + string.digits
115-
encoded = ''
116-
if choice == "encode":
117-
for letter in word:
118-
if letter == ' ':
119-
encoded = encoded + ' '
120-
else:
121-
x = letters.index(letter) + shift
122-
encoded = encoded + letters[x]
123-
if choice == "decode":
124-
for letter in word:
125-
if letter == ' ':
126-
encoded = encoded + ' '
127-
else:
128-
x = letters.index(letter) - shift
129-
encoded = encoded + letters[x]
75+
import string
13076

131-
print(encoded)
77+
shift = 3
78+
choice = input("would you like to encode or decode?")
79+
word = input("Please enter text")
80+
letters = string.ascii_letters + string.punctuation + string.digits
81+
encoded = ""
82+
if choice == "encode":
83+
for letter in word:
84+
if letter == " ":
85+
encoded = encoded + " "
86+
else:
87+
x = letters.index(letter) + shift
88+
encoded = encoded + letters[x]
89+
if choice == "decode":
90+
for letter in word:
91+
if letter == " ":
92+
encoded = encoded + " "
93+
else:
94+
x = letters.index(letter) - shift
95+
encoded = encoded + letters[x]
13296

97+
print(encoded)
13398

134-
Let's get started.
13599

136-
If we run this:
100+
Let's get started. If we run this:
137101

138102
.. sourcecode:: console
139103

140-
robertk01 Desktop$ pylint simplecaesar.py
141-
************* Module simplecaesar
142-
simplecaesar.py:3:0: W0301: Unnecessary semicolon (unnecessary-semicolon)
143-
simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)
144-
simplecaesar.py:5:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
145-
simplecaesar.py:9:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
146-
simplecaesar.py:13:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
104+
tutor Desktop$ pylint simplecaesar.py
105+
************* Module simplecaesar
106+
simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)
107+
simplecaesar.py:5:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
108+
simplecaesar.py:8:0: C0103: Constant name "letters" doesn't conform to UPPER_CASE naming style (invalid-name)
109+
simplecaesar.py:9:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
110+
simplecaesar.py:13:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
111+
simplecaesar.py:15:12: C0103: Constant name "x" doesn't conform to UPPER_CASE naming style (invalid-name)
112+
simplecaesar.py:16:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
113+
simplecaesar.py:20:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
114+
simplecaesar.py:22:12: C0103: Constant name "x" doesn't conform to UPPER_CASE naming style (invalid-name)
115+
simplecaesar.py:23:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
147116

148-
-----------------------------------
149-
Your code has been rated at 7.37/10
117+
-----------------------------------
118+
Your code has been rated at 4.74/10
150119

151120

152-
Previous experience taught me that the default output for the messages
153-
needed a bit more info. We can see the second line is: ::
121+
We can see the second line is: ::
154122

155123
"simplecaesar.py:1:0: C0114: Missing module docstring (missing-module-docstring)"
156124

157-
This basically means that line 1 violates a convention ``C0114``. It's telling me I really should have a docstring.
158-
I agree, but what if I didn't fully understand what rule I violated. Knowing only that I violated a convention
159-
isn't much help if I'm a newbie. Another piece of information there is the
160-
message symbol between parens, ``missing-module-docstring`` here.
125+
This basically means that line 1 at column 0 violates the convention ``C0114``.
126+
Another piece of information is the message symbol between parens,
127+
``missing-module-docstring``.
161128

162-
If I want to read up a bit more about that, I can go back to the
129+
If we want to read up a bit more about that, we can go back to the
163130
command line and try this:
164131

165132
.. sourcecode:: console
166133

167-
robertk01 Desktop$ pylint --help-msg=missing-module-docstring
134+
tutor Desktop$ pylint --help-msg=missing-module-docstring
168135
:missing-module-docstring (C0114): *Missing module docstring*
169136
Used when a module has no docstring.Empty modules do not require a docstring.
170137
This message belongs to the basic checker.
171138

172-
173-
Yeah, ok. That one was a bit of a no-brainer, but I have run into error messages
174-
that left me with no clue about what went wrong, simply because I was unfamiliar
175-
with the underlying mechanism of code theory. One error that puzzled my newbie
176-
mind was: ::
177-
178-
:too-many-instance-attributes (R0902): *Too many instance attributes (%s/%s)*
179-
180-
I get it now thanks to Pylint pointing it out to me. If you don't get that one,
181-
pour a fresh cup of coffee and look into it - let your programmer mind grow!
182-
139+
That one was a bit of a no-brainer, but we can also run into error messages
140+
where we are unfamiliar with the underlying code theory.
183141

184142
The Next Step
185143
-------------
186144

187145
Now that we got some configuration stuff out of the way, let's see what we can
188-
do with the remaining warnings.
189-
190-
If we add a docstring to describe what the code is meant to do that will help.
191-
There are 5 ``invalid-name`` messages that we will get to later. Lastly, I
192-
put an unnecessary semicolon at the end of the import line so I'll
193-
fix that too. To sum up, I'll add a docstring to line 2, and remove the ``;``
194-
from line 3.
195-
196-
Here is the updated code:
146+
do with the remaining warnings. If we add a docstring to describe what the code
147+
is meant to do that will help. There are ``invalid-name`` messages that we will
148+
get to later. Here is the updated code:
197149

198150
.. sourcecode:: python
199151

200-
#!/usr/bin/env python3
201-
"""This script prompts a user to enter a message to encode or decode
202-
using a classic Caesar shift substitution (3 letter shift)"""
203-
204-
import string
205-
206-
shift = 3
207-
choice = input("would you like to encode or decode?")
208-
word = input("Please enter text")
209-
letters = string.ascii_letters + string.punctuation + string.digits
210-
encoded = ''
211-
if choice == "encode":
212-
for letter in word:
213-
if letter == ' ':
214-
encoded = encoded + ' '
215-
else:
216-
x = letters.index(letter) + shift
217-
encoded = encoded + letters[x]
218-
if choice == "decode":
219-
for letter in word:
220-
if letter == ' ':
221-
encoded = encoded + ' '
222-
else:
223-
x = letters.index(letter) - shift
224-
encoded = encoded + letters[x]
225-
226-
print(encoded)
152+
#!/usr/bin/env python3
153+
154+
"""This script prompts a user to enter a message to encode or decode
155+
using a classic Caesar shift substitution (3 letter shift)"""
156+
157+
import string
158+
159+
shift = 3
160+
choice = input("would you like to encode or decode?")
161+
word = input("Please enter text")
162+
letters = string.ascii_letters + string.punctuation + string.digits
163+
encoded = ""
164+
if choice == "encode":
165+
for letter in word:
166+
if letter == " ":
167+
encoded = encoded + " "
168+
else:
169+
x = letters.index(letter) + shift
170+
encoded = encoded + letters[x]
171+
if choice == "decode":
172+
for letter in word:
173+
if letter == " ":
174+
encoded = encoded + " "
175+
else:
176+
x = letters.index(letter) - shift
177+
encoded = encoded + letters[x]
178+
179+
print(encoded)
227180

228181
Here is what happens when we run it:
229182

230183
.. sourcecode:: console
231184

232-
robertk01 Desktop$ pylint simplecaesar.py
233-
************* Module simplecaesar
234-
simplecaesar.py:7:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
235-
simplecaesar.py:11:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
236-
simplecaesar.py:15:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
185+
tutor Desktop$ pylint simplecaesar.py
186+
************* Module simplecaesar
187+
simplecaesar.py:8:0: C0103: Constant name "shift" doesn't conform to UPPER_CASE naming style (invalid-name)
188+
simplecaesar.py:11:0: C0103: Constant name "letters" doesn't conform to UPPER_CASE naming style (invalid-name)
189+
simplecaesar.py:12:0: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
190+
simplecaesar.py:16:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
191+
simplecaesar.py:18:12: C0103: Constant name "x" doesn't conform to UPPER_CASE naming style (invalid-name)
192+
simplecaesar.py:19:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
193+
simplecaesar.py:23:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
194+
simplecaesar.py:25:12: C0103: Constant name "x" doesn't conform to UPPER_CASE naming style (invalid-name)
195+
simplecaesar.py:26:12: C0103: Constant name "encoded" doesn't conform to UPPER_CASE naming style (invalid-name)
237196

238-
------------------------------------------------------------------
239-
Your code has been rated at 8.42/10 (previous run: 7.37/10, +1.05)
197+
------------------------------------------------------------------
198+
Your code has been rated at 5.26/10 (previous run: 4.74/10, +0.53)
240199

241-
Nice! Pylint told us how much our code rating has improved since our last run, and we're down to just the ``invalid-name`` messages.
200+
Nice! Pylint told us how much our code rating has improved since our last run,
201+
and we're down to just the ``invalid-name`` messages.
242202

243203
There are fairly well defined conventions around naming things like instance
244204
variables, functions, classes, etc. The conventions focus on the use of
245205
UPPERCASE and lowercase as well as the characters that separate multiple words
246206
in the name. This lends itself well to checking via a regular expression, thus
247207
the **should match (([A-Z\_][A-Z1-9\_]*)|(__.*__))$**.
248208

249-
In this case Pylint is telling me that those variables appear to be constants
209+
In this case Pylint is telling us that those variables appear to be constants
250210
and should be all UPPERCASE. This is an in-house convention that has lived with Pylint
251211
since its inception. You too can create your own in-house naming
252212
conventions but for the purpose of this tutorial, we want to stick to the `PEP 8`_
253-
standard. In this case, the variables I declared should follow the convention
213+
standard. In this case, the variables we declared should follow the convention
254214
of all lowercase. The appropriate rule would be something like:
255215
"should match [a-z\_][a-z0-9\_]{2,30}$". Notice the lowercase letters in the
256216
regular expression (a-z versus A-Z).
@@ -260,14 +220,15 @@ will now be quite quiet:
260220

261221
.. sourcecode:: console
262222

263-
robertk01 Desktop$ pylint --const-rgx='[a-z_][a-z0-9_]{2,30}$' simplecaesar.py
223+
tutor Desktop$ pylint simplecaesar.py --const-rgx='[a-z\_][a-z0-9\_]{2,30}$'
224+
************* Module simplecaesar
225+
simplecaesar.py:18:12: C0103: Constant name "x" doesn't conform to '[a-z\\_][a-z0-9\\_]{2,30}$' pattern (invalid-name)
226+
simplecaesar.py:25:12: C0103: Constant name "x" doesn't conform to '[a-z\\_][a-z0-9\\_]{2,30}$' pattern (invalid-name)
264227

265-
-------------------------------------------------------------------
266-
Your code has been rated at 10.00/10 (previous run: 8.42/10, +1.58)
228+
------------------------------------------------------------------
229+
Your code has been rated at 8.95/10 (previous run: 5.26/10, +3.68)
267230

268-
269-
Regular expressions can be quite a beast so take my word on this particular
270-
example but go ahead and `read up`_ on them if you want.
231+
You can `read up`_ on regular expressions or use `a website to help you`_.
271232

272233
.. tip::
273234
It would really be a pain to specify that regex on the command line all the time, particularly if we're using many other options.
@@ -276,6 +237,5 @@ example but go ahead and `read up`_ on them if you want.
276237
quickly sharing them with others. Invoking ``pylint --generate-toml-config`` will create a sample ``.toml`` section with all the options set and explained in comments.
277238
This can then be added to your ``pyproject.toml`` file or any other ``.toml`` file pointed to with the ``--rcfile`` option.
278239

279-
That's it for the basic intro. More tutorials will follow.
280-
281240
.. _`read up`: https://docs.python.org/library/re.html
241+
.. _`a website to help you`: https://regex101.com/

0 commit comments

Comments
 (0)