@@ -27,18 +27,19 @@ We can also use tools,
2727called [ ** code linters** ] ( https://en.wikipedia.org/wiki/Lint_%28software%29 ) ,
2828to identify consistency issues in a report-style.
2929Linters analyse source code to identify and report on stylistic and even programming errors.
30- Let us look at a very well used one of these called ` pylint ` .
30+ Let us look at a very well used one of these called ` ruff ` .
3131
3232First, let us ensure we are on the ` style-fixes ` branch once again.
3333
3434``` bash
3535$ git switch style-fixes
3636```
3737
38- Pylint is just a Python package so we can install it in our virtual environment using:
38+ Ruff is written in Rust, which makes it very fast as compared to other Python linters.
39+ It can be installed in our virtual environment using ` pip ` :
3940
4041``` bash
41- $ python3 -m pip install pylint
42+ $ python3 -m pip install ruff
4243```
4344
4445We should also update our ` requirements.txt ` with this new addition:
@@ -47,18 +48,20 @@ We should also update our `requirements.txt` with this new addition:
4748$ python3 -m pip freeze --exclude-editable > requirements.txt
4849```
4950
50- Pylint is a command-line tool that can help our code in many ways:
51+ Ruff is a command-line tool that can help our code in many ways:
5152
5253- ** Check PEP 8 compliance:**
5354 whilst in-IDE context-sensitive highlighting helps us stay consistent with PEP 8 as we write code, this tool provides a full report
54- - ** Perform basic error detection:** Pylint can look for certain Python type errors
55+ - ** Perform basic error detection:** Ruff can look for certain Python type errors
5556- ** Check variable naming conventions** :
56- Pylint often goes beyond PEP 8 to include other common conventions,
57+ Ruff can go beyond PEP 8 to include other common conventions,
5758 such as naming variables outside of functions in upper case
5859- ** Customisation** :
5960 you can specify which errors and conventions you wish to check for, and those you wish to ignore
61+ - ** Automatic fixes** :
62+ Ruff supports automatic fixes for some lint errors.
6063
61- Pylint can also identify ** code smells** .
64+ Ruff can also identify ** code smells** .
6265
6366::::::::::::::::::::::::::::::::::::::::: callout
6467
@@ -82,92 +85,170 @@ by Kent Beck and Martin Fowler in
8285
8386::::::::::::::::::::::::::::::::::::::::::::::::::
8487
85- Pylint recommendations are given as warnings or errors,
86- and Pylint also scores the code with an overall mark.
88+ In addition, Ruff includes the functionality of a formatter: it can be used
89+ to apply a stardardized format to Python files, so that the resulting layout
90+ makes the code more consistent and readable. We will not cover Ruff's use as
91+ a formatter here, but you can learn more about this topic from the
92+ [ Ruff documentation] ( https://docs.astral.sh/ruff/formatter/ ) .
93+
94+ Ruff recommendations are given as warnings or errors.
8795We can look at a specific file (e.g. ` inflammation-analysis.py ` ),
8896or a package (e.g. ` inflammation ` ).
8997Let us look at our ` inflammation ` package and code inside it (namely ` models.py ` and ` views.py ` ).
9098From the project root do:
9199
92100``` bash
93- $ pylint inflammation
101+ $ ruff check inflammation
94102```
95103
96104You should see an output similar to the following:
97105
98106``` output
99- ************* Module inflammation.models
100- inflammation/models.py:13:23: C0303: Trailing whitespace (trailing-whitespace)
101- inflammation/models.py:34:0: C0305: Trailing newlines (trailing-newlines)
102- ************* Module inflammation.views
103- inflammation/views.py:4:0: W0611: Unused numpy imported as np (unused-import)
104-
105- ------------------------------------------------------------------
106- Your code has been rated at 8.50/10 (previous run: 8.50/10, +0.00)
107+ F401 [*] `numpy` imported but unused
108+ --> inflammation/views.py:4:17
109+ |
110+ 3 | from matplotlib import pyplot as plt
111+ 4 | import numpy as np
112+ | ^^
113+ |
114+ help: Remove unused import: `numpy`
115+
116+ Found 1 error.
117+ [*] 1 fixable with the `--fix` option.
107118```
108119
109120Your own outputs of the above commands may vary depending on
110121how you have implemented and fixed the code in previous exercises
111122and the coding style you have used.
112123
113- The five digit codes, such as ` C0303 ` , are unique identifiers for warnings,
114- with the first character indicating the type of warning.
115- There are five different types of warnings that Pylint looks for,
116- and you can get a summary of them by doing:
124+ The alphanumeric codes, such as ` F401 ` , are unique identifiers for lint rules.
125+ Ruff implements rules as derived by other tools and conventions - the starting
126+ letter of the code refers to the tool or convention the rule is derived from.
127+ To learn more about a lint rule, e.g. ` F401 ` , you can run:
128+
129+ ``` bash
130+ $ ruff rule F401
131+ ```
132+ Ruff will tell you that ` F401 ` , as all other ` F ` -rules, are derived from the
133+ [ Pyflakes] ( https://pypi.org/project/pyflakes/ ) Python linter, and give you
134+ examples, explanations and some reasoning on why the rule exists.
135+ The full list of rules that Ruff supports is available
136+ [ as part of the Ruff documentation] ( https://docs.astral.sh/ruff/rules/ ) .
137+
138+ Note that by default Ruff does not check for all rules, but it enables
139+ only a subset that is considered a reasonable choice to identify common errors.
140+ You can enable a specific set of rules using the ` --select ` option. For instance,
141+ try to include the following set of rules, which are derived from some of the most
142+ popular tools, such as [ pycodestyle] ( https://pypi.org/project/pycodestyle/ )
143+ (` E ` and ` W ` rules) and [ isort] ( https://pypi.org/project/isort/ ) (` I ` rules):
117144
118145``` bash
119- $ pylint --long-help
146+ $ ruff check --select E,W,F,UP,A,B,SIM,I inflammation
120147```
121148
122- Near the end you'll see :
149+ Ruff will identify more problems in the codebase :
123150
124151``` output
125- Output:
126- Using the default text output, the message format is :
127- MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE
128- There are 5 kind of message types :
129- * (C) convention, for programming standard violation
130- * (R) refactor, for bad code smell
131- * (W) warning, for python specific problems
132- * (E) error, for probable bugs in the code
133- * (F) fatal, if an error occurred which prevented pylint from doing
134- further processing.
152+ W291 Trailing whitespace
153+ --> inflammation/models.py:5:83
154+ |
155+ 3 | The Model layer is responsible for the 'business logic' part of the software.
156+ 4 |
157+ 5 | Patients' data is held in an inflammation table (2D array) where each row contains
158+ | ^
159+ 6 | inflammation data for a single patient taken over a number of days
160+ 7 | and each column represents a single day across all patients.
161+ |
162+ help: Remove trailing whitespace
163+
164+ W291 Trailing whitespace
165+ --> inflammation/models.py:6:67
166+ |
167+ 5 | Patients' data is held in an inflammation table (2D array) where each row contains
168+ 6 | inflammation data for a single patient taken over a number of days
169+ | ^
170+ 7 | and each column represents a single day across all patients.
171+ 8 | """
172+ |
173+ help: Remove trailing whitespace
174+
175+ W291 [*] Trailing whitespace
176+ --> inflammation/models.py:13:24
177+ |
178+ 13 | def load_csv(filename):
179+ | ^^
180+ 14 | """Load a Numpy array from a CSV
181+ |
182+ help: Remove trailing whitespace
183+
184+ I001 [*] Import block is un-sorted or un-formatted
185+ --> inflammation/views.py:3:1
186+ |
187+ 1 | """Module containing code for plotting inflammation data."""
188+ 2 |
189+ 3 | / from matplotlib import pyplot as plt
190+ 4 | | import numpy as np
191+ | |__________________^
192+ |
193+ help: Organize imports
194+
195+ F401 [*] `numpy` imported but unused
196+ --> inflammation/views.py:4:17
197+ |
198+ 3 | from matplotlib import pyplot as plt
199+ 4 | import numpy as np
200+ | ^^
201+ |
202+ help: Remove unused import: `numpy`
203+
204+ Found 5 errors.
205+ [*] 3 fixable with the `--fix` option (2 hidden fixes can be enabled with the `--unsafe-fixes` option).
135206```
136207
137- So for an example of a Pylint Python-specific ` warning ` ,
138- see the "W0611: Unused numpy imported as np (unused-import)" warning.
139-
140- It is important to note that while tools such as Pylint are great at giving you
208+ It is important to note that while tools such as Ruff are great at giving you
141209a starting point to consider how to improve your code,
142210they will not find everything that may be wrong with it.
143211
144- ::::::::::::::::::::::::::::::::::::::::: callout
212+ ::::::::::::::::::::::::::::::::::::::: challenge
145213
146- ## How Does Pylint Calculate the Score?
214+ ## Exercise: Add Ruff configurations to the ` pyproject.toml ` file
147215
148- The Python formula used is
149- (with the variables representing numbers of each type of infraction
150- and ` statement ` indicating the total number of statements):
216+ You can define the Ruff configuration for a project by adding a section to the
217+ ` pyproject.toml ` file. For instance, you can define the set of rules to be checked
218+ for your codebase. Following [ the Ruff documentation] ( https://docs.astral.sh/ruff/linter/ ) ,
219+ add a section to the ` pyproject.toml ` to enable the ` E ` , ` W ` , ` F ` , ` UP ` , ` A ` , ` B ` , ` SIM ` ,
220+ and ` I ` rules for the project. Verify that the configuration is respected when running
221+ ` ruff ` (without the ` --select ` option):
151222
152223``` bash
153- 10.0 - (( float(5 * error + warning + refactor + convention) / statement) * 10 )
224+ $ ruff check inflammation
225+ ```
226+
227+ :::::::::::::::::::::::::::::::: solution
228+
229+ Add the following section to the ` pyproject.toml ` :
230+
231+ ``` toml
232+ [tool .ruff .lint ]
233+ select = [" E" , " W" , " F" , " UP" , " A" , " B" , " SIM" , " I" ]
154234```
155235
156- For example, with a total of 31 statements of models.py and views.py,
157- with a count of the errors shown above, we get a score of 8 .00 .
158- Note whilst there is a maximum score of 10 , given the formula,
159- there is no minimum score - it is quite possible to get a negative score!
236+ Running ` ruff check inflammation ` should indeed show problems with some of
237+ the ` W ` and ` I ` rules, which are not enabled with the default Ruff settings.
160238
239+ ::::::::::::::::::::::::::::::::::::::::::
161240
162241::::::::::::::::::::::::::::::::::::::::::::::::::
163242
164243::::::::::::::::::::::::::::::::::::::: challenge
165244
166245## Exercise: Further Improve Code Style of Our Project
167246
168- Select and fix a few of the issues with our code that Pylint detected.
169- Make sure you do not break the rest of the code in the process and that the code still runs.
170- After making any changes, run Pylint again to verify you have resolved these issues.
247+ Select and fix a few of the issues with our code that Ruff detected.
248+ You can try using the Ruff's ` --fix ` command-line option to automatically fix
249+ (some of) the issues. If you manually edit the code, make sure you do not break
250+ the rest of the code in the process and that the code still runs.
251+ After making any changes, run Ruff again to verify you have resolved these issues.
171252
172253::::::::::::::::::::::::::::::::::::::::::::::::::
173254
@@ -185,7 +266,7 @@ with GitHub Actions - we will come back to automated linting in the episode on
185266
186267``` bash
187268$ git add requirements.txt
188- $ git commit -m "Added Pylint library"
269+ $ git commit -m " Added Ruff library"
189270$ git push origin style-fixes
190271$ git switch develop
191272$ git merge style-fixes
@@ -197,17 +278,16 @@ $ git push origin develop
197278## Optional Exercise: Improve Code Style of Your Other Python Projects
198279
199280If you have a Python project you are working on or you worked on in the past,
200- run it past Pylint to see what issues with your code are detected, if any.
201-
281+ run it past Ruff to see what issues with your code are detected, if any.
202282
203283::::::::::::::::::::::::::::::::::::::::::::::::::
204284
205285::: challenge
206286
207- ## Optional Exercise: More on Pylint
287+ ## Optional Exercise: More on Ruff
208288
209289Checkout [ this optional exercise] ( 17-section1-optional-exercises.md )
210- to learn more about `pylint `.
290+ to learn more about ` ruff ` .
211291
212292:::
213293
0 commit comments