@@ -16,13 +16,13 @@ numbers
16
16
Where ` numbers.py ` contains the following code:
17
17
18
18
``` py
19
- from typing import List
19
+ from typing import Iterable
20
20
21
21
import os
22
22
23
23
24
- def sum_even_numbers (numbers : List [int ]) -> int :
25
- """ Given a list of integers, return the sum of all even numbers in the list ."""
24
+ def sum_even_numbers (numbers : Iterable [int ]) -> int :
25
+ """ Given a sequence of integers, return the sum of all even numbers in the sequence ."""
26
26
return sum (num for num in numbers if num % 2 == 0 )
27
27
```
28
28
@@ -32,17 +32,17 @@ To start, we'll install Ruff through PyPI (or with your [preferred package manag
32
32
> pip install ruff
33
33
```
34
34
35
- We can then run Ruff over our project via:
35
+ We can then run Ruff over our project via ` ruff check ` :
36
36
37
37
``` shell
38
38
❯ ruff check .
39
39
numbers/numbers.py:3:8: F401 [* ] ` os` imported but unused
40
40
Found 1 error.
41
- [* ] 1 potentially fixable with the --fix option.
41
+ [* ] 1 fixable with the ` --fix` option.
42
42
```
43
43
44
44
Ruff identified an unused import, which is a common error in Python code. Ruff considers this a
45
- "fixable" error, so we can resolve the issue automatically by running:
45
+ "fixable" error, so we can resolve the issue automatically by running ` ruff check --fix ` :
46
46
47
47
``` shell
48
48
❯ ruff check --fix .
@@ -55,13 +55,13 @@ Running `git diff` shows the following:
55
55
--- a/numbers/numbers.py
56
56
+++ b/numbers/numbers.py
57
57
@@ -1,7 +1,5 @@
58
- from typing import List
58
+ from typing import Iterable
59
59
60
60
- import os
61
61
-
62
62
63
- def sum_even_numbers(numbers: List [int]) -> int:
64
- """Given a list of integers, return the sum of all even numbers in the list ."""
63
+ def sum_even_numbers(numbers: Iterable [int]) -> int:
64
+ """Given a sequence of integers, return the sum of all even numbers in the sequence ."""
65
65
return sum(num for num in numbers if num % 2 == 0)
66
66
```
67
67
@@ -77,15 +77,19 @@ Let's create a `pyproject.toml` file in our project's root directory:
77
77
78
78
``` toml
79
79
[tool .ruff ]
80
- # Decrease the maximum line length to 79 characters.
80
+ # Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that
81
+ # overlap with the use of a formatter, like Black, but we can override this behavior by
82
+ # explicitly adding the rule.
83
+ extend-select = [" E501" ]
84
+ # Set the maximum line length to 79 characters.
81
85
line-length = 79
82
86
```
83
87
84
88
Running Ruff again, we can see that it now enforces a line length of 79 characters:
85
89
86
90
``` shell
87
91
❯ ruff check .
88
- numbers/numbers.py:6 :80: E501 Line too long (83 > 79 characters)
92
+ numbers/numbers.py:5 :80: E501 Line too long (90 > 79 characters)
89
93
Found 1 error.
90
94
```
91
95
@@ -98,9 +102,10 @@ specifically, we'll want to make note of the minimum supported Python version:
98
102
requires-python = " >=3.10"
99
103
100
104
[tool .ruff ]
101
- # Decrease the maximum line length to 79 characters.
105
+ # Add the `line-too-long` rule to the enforced rule set.
106
+ extend-select = [" E501" ]
107
+ # Set the maximum line length to 79 characters.
102
108
line-length = 79
103
- src = [" src" ]
104
109
```
105
110
106
111
### Rule Selection
@@ -109,45 +114,47 @@ Ruff supports [over 700 lint rules](rules.md) split across over 50 built-in plug
109
114
determining the right set of rules will depend on your project's needs: some rules may be too
110
115
strict, some are framework-specific, and so on.
111
116
112
- By default, Ruff enforces the ` E ` - and ` F ` -prefixed rules, which correspond to those derived from
113
- pycodestyle and Pyflakes, respectively.
117
+ By default, Ruff enables Flake8's ` F ` rules, along with a subset of the ` E ` rules, omitting any
118
+ stylistic rules that overlap with the use of a formatter, like
119
+ [ Black] ( https://github.com/psf/black ) .
114
120
115
121
If you're introducing a linter for the first time, ** the default rule set is a great place to
116
122
start** : it's narrow and focused while catching a wide variety of common errors (like unused
117
123
imports) with zero configuration.
118
124
119
125
If you're migrating to Ruff from another linter, you can enable rules that are equivalent to
120
126
those enforced in your previous configuration. For example, if we want to enforce the pyupgrade
121
- rules, we can add the following to our ` pyproject.toml ` :
127
+ rules, we can set our ` pyproject.toml ` to the following :
122
128
123
129
``` toml
130
+ [project ]
131
+ requires-python = " >=3.10"
132
+
124
133
[tool .ruff ]
125
- select = [
126
- " E" , # pycodestyle
127
- " F" , # pyflakes
134
+ extend-select = [
128
135
" UP" , # pyupgrade
129
136
]
130
137
```
131
138
132
139
If we run Ruff again, we'll see that it now enforces the pyupgrade rules. In particular, Ruff flags
133
- the use of ` List ` instead of its standard-library variant :
140
+ the use of the deprecated ` typing.Iterable ` instead of ` collections.abc.Iterable ` :
134
141
135
142
``` shell
136
143
❯ ruff check .
137
- numbers/numbers.py:5:31: UP006 [* ] Use ` list` instead of ` List` for type annotations
138
- numbers/numbers.py:6:80: E501 Line too long (83 > 79 characters)
139
- Found 2 errors.
140
- [* ] 1 potentially fixable with the --fix option.
144
+ numbers/numbers.py:1:1: UP035 [* ] Import from ` collections.abc` instead: ` Iterable`
145
+ Found 1 error.
146
+ [* ] 1 fixable with the ` --fix` option.
141
147
```
142
148
143
149
Over time, we may choose to enforce additional rules. For example, we may want to enforce that
144
150
all functions have docstrings:
145
151
146
152
``` toml
153
+ [project ]
154
+ requires-python = " >=3.10"
155
+
147
156
[tool .ruff ]
148
- select = [
149
- " E" , # pycodestyle
150
- " F" , # pyflakes
157
+ extend-select = [
151
158
" UP" , # pyupgrade
152
159
" D" , # pydocstyle
153
160
]
@@ -161,52 +168,49 @@ If we run Ruff again, we'll see that it now enforces the pydocstyle rules:
161
168
``` shell
162
169
❯ ruff check .
163
170
numbers/__init__.py:1:1: D104 Missing docstring in public package
171
+ numbers/numbers.py:1:1: UP035 [* ] Import from ` collections.abc` instead: ` Iterable`
164
172
numbers/numbers.py:1:1: D100 Missing docstring in public module
165
- numbers/numbers.py:5:31: UP006 [* ] Use ` list` instead of ` List` for type annotations
166
- numbers/numbers.py:5:80: E501 Line too long (83 > 79 characters)
167
173
Found 3 errors.
168
- [* ] 1 potentially fixable with the --fix option.
174
+ [* ] 1 fixable with the ` --fix` option.
169
175
```
170
176
171
177
### Ignoring Errors
172
178
173
179
Any lint rule can be ignored by adding a ` # noqa ` comment to the line in question. For example,
174
- let's ignore the ` UP006 ` rule for the ` List ` import:
180
+ let's ignore the ` UP035 ` rule for the ` Iterable ` import:
175
181
176
182
``` py
177
- from typing import List
183
+ from typing import Iterable # noqa: UP035
178
184
179
185
180
- def sum_even_numbers (numbers : List [int ]) -> int : # noqa: UP006
181
- """ Given a list of integers, return the sum of all even numbers in the list ."""
186
+ def sum_even_numbers (numbers : Iterable [int ]) -> int :
187
+ """ Given a sequence of integers, return the sum of all even numbers in the sequence ."""
182
188
return sum (num for num in numbers if num % 2 == 0 )
183
189
```
184
190
185
- Running Ruff again, we'll see that it no longer flags the ` List ` import:
191
+ Running Ruff again, we'll see that it no longer flags the ` Iterable ` import:
186
192
187
193
``` shell
188
194
❯ ruff check .
189
195
numbers/__init__.py:1:1: D104 Missing docstring in public package
190
196
numbers/numbers.py:1:1: D100 Missing docstring in public module
191
- numbers/numbers.py:5:80: E501 Line too long (83 > 79 characters)
192
197
Found 3 errors.
193
198
```
194
199
195
200
If we want to ignore a rule for an entire file, we can add a ` # ruff: noqa ` comment to the top of
196
201
the file:
197
202
198
203
``` py
199
- # ruff: noqa: UP006
200
- from typing import List
204
+ # ruff: noqa: UP035
205
+ from typing import Iterable
201
206
202
207
203
- def sum_even_numbers (numbers : List [int ]) -> int :
204
- """ Given a list of integers, return the sum of all even numbers in the list ."""
208
+ def sum_even_numbers (numbers : Iterable [int ]) -> int :
209
+ """ Given a sequence of integers, return the sum of all even numbers in the sequence ."""
205
210
return sum (num for num in numbers if num % 2 == 0 )
206
211
```
207
212
208
- For more in-depth instructions on ignoring errors,
209
- please see [ _ Configuration_ ] ( configuration.md#error-suppression ) .
213
+ For more in-depth instructions on ignoring errors, see [ _ Configuration_ ] ( configuration.md#error-suppression ) .
210
214
211
215
### Adding Rules
212
216
@@ -215,10 +219,10 @@ violations of that rule and instead focus on enforcing it going forward.
215
219
216
220
Ruff enables this workflow via the ` --add-noqa ` flag, which will adds a ` # noqa ` directive to each
217
221
line based on its existing violations. We can combine ` --add-noqa ` with the ` --select ` command-line
218
- flag to add ` # noqa ` directives to all existing ` UP006 ` violations:
222
+ flag to add ` # noqa ` directives to all existing ` UP035 ` violations:
219
223
220
224
``` shell
221
- ❯ ruff check --select UP006 --add-noqa .
225
+ ❯ ruff check --select UP035 --add-noqa .
222
226
Added 1 noqa directive.
223
227
```
224
228
@@ -229,14 +233,12 @@ diff --git a/tutorial/src/main.py b/tutorial/src/main.py
229
233
index b9291c5ca..b9f15b8c1 100644
230
234
--- a/numbers/numbers.py
231
235
+++ b/numbers/numbers.py
232
- @@ -1,6 +1,6 @@
233
- from typing import List
236
+ @@ -1,4 +1,4 @@
237
+ - from typing import Iterable
238
+ + from typing import Iterable # noqa: UP035
234
239
235
240
236
- - def sum_even_numbers(numbers: List[int]) -> int:
237
- + def sum_even_numbers(numbers: List[int]) -> int: # noqa: UP006
238
- """Given a list of integers, return the sum of all even numbers in the list."""
239
- return sum(num for num in numbers if num % 2 == 0)
241
+ def sum_even_numbers(numbers: Iterable[int]) -> int:
240
242
```
241
243
242
244
## Continuous Integration
0 commit comments