Skip to content

Commit 5158d0f

Browse files
authored
Merge pull request #3 from esciencecenter-digital-skills/main
Update to NL eScience centre version.
2 parents 1dfe857 + 585e9b8 commit 5158d0f

32 files changed

Lines changed: 1096 additions & 590 deletions

config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ episodes:
8282
- 22-scaling-up-unit-testing.md
8383
- 23-continuous-integration-automated-testing.md
8484
- 24-diagnosing-issues-improving-robustness.md
85-
- 25-section2-optional-exercises.md
85+
- 25-type-annotation.md
86+
- 26-section2-optional-exercises.md
8687
- 30-section3-intro.md
8788
- 31-software-requirements.md
8889
- 32-software-architecture-design.md

episodes/12-virtual-environments.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,16 @@ There are several commonly used command line tools for managing Python virtual e
135135
- `conda`, package and environment management system
136136
(also included as part of the Anaconda Python distribution often used by the scientific community)
137137
- `poetry`, a modern Python packaging tool which handles virtual environments automatically
138+
- `uv`, a recent and fast package, environment, and project manager.
138139

139140
While there are pros and cons for using each of the above,
140141
all will do the job of managing Python virtual environments for you
141142
and it may be a matter of personal preference which one you go for.
142-
In this course, we will use `venv` to create and manage our virtual environment
143-
(which is the preferred way for Python 3.3+).
144-
The upside is that `venv` virtual environments created from the command line are
145-
also recognised and picked up automatically by the IDEs we will use in this course,
146-
as we will see in the next episode.
143+
In this course, we will use `venv` to create and manage our virtual environment, which
144+
is the tool that is part of the standard Python installation and the recommended manager
145+
for Python 3.5+. If you want to experiment with a fast alternative that can work
146+
as a drop-in replacement for `venv`, have a look at `uv` (see also the
147+
[callout below](#uv-callout)).
147148

148149
### Managing External Packages
149150

@@ -170,6 +171,22 @@ from remote package repositories and install them on your system, and
170171
So, you can use `conda` for both tasks instead of using `venv` and `pip`.
171172

172173

174+
::::::::::::::::::::::::::::::::::::::::::::::::::
175+
176+
<a id="uv-callout"></a>
177+
178+
::::::::::::::::::::::::::::::::::::::::: callout
179+
180+
## A recent addition: `uv`
181+
182+
[`uv`](https://docs.astral.sh/uv/) is becoming increasingly popular in the world of
183+
Python package and project managers. Similarly to `conda`, it combines the functionality
184+
of a package manager (finding and installing Python packages) and a virtual environment
185+
manager (isolating project dependecies), but it can also be used to create and manage
186+
Python projects, update dependencies, publishing packages, and much more. Its sub-commands
187+
`uv venv` and `uv pip` can be used as a drop-in replacement for `venv` and `pip`,
188+
respectively, which the additional advantage of being much faster!
189+
173190
::::::::::::::::::::::::::::::::::::::::::::::::::
174191

175192
### Many Tools for the Job
@@ -209,7 +226,7 @@ You can test your Python installation from the command line with:
209226

210227
```bash
211228
$ python3 --version # on Mac/Linux
212-
$ python --version # on Windows — Windows installation comes with a python.exe file rather than a python3.exe file
229+
$ python --version # on Windows — Windows installation comes with a python.exe file rather than a python3.exe file
213230
```
214231

215232
If you are using Windows and invoking `python` command causes your Git Bash terminal to hang with no error message or output, you may
@@ -312,7 +329,7 @@ Here are some references for each of the naming conventions:
312329
- [The Python Documentation](https://docs.python.org/3/library/venv.html)
313330
indicates that ".venv" is common
314331
- ["venv" vs ".venv" discussion](https://discuss.python.org/t/trying-to-come-up-with-a-default-directory-name-for-virtual-environments/3750)
315-
332+
316333

317334
::::::::::::::::::::::::::::::::::::::::::::::::::
318335

@@ -449,7 +466,7 @@ Version: 1.26.2
449466
Summary: Fundamental package for array computing in Python
450467
Home-page: https://numpy.org
451468
Author: Travis E. Oliphant et al.
452-
Author-email:
469+
Author-email:
453470
License: Copyright (c) 2005-2023, NumPy Developers.
454471
All rights reserved.
455472
...
@@ -639,7 +656,7 @@ In the above command, we tell the command line two things:
639656
As we can see, the Python interpreter ran our script, which threw an error -
640657
`inflammation-analysis.py: error: the following arguments are required: infiles`.
641658
It looks like the script expects a list of input files to process,
642-
so this is expected behaviour since we do not supply any.
659+
so this is expected behaviour since we do not supply any.
643660

644661
We should run our code as follows, passing one (or more) data file(s) as input:
645662

episodes/13-ides.md

Lines changed: 68 additions & 64 deletions
Large diffs are not rendered by default.

episodes/14-collaboration-using-git.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ sequenceDiagram
113113
Staging Area->>+Local Repository: git commit
114114
Local Repository->>+Remote Repository: git push
115115
Remote Repository->>+Local Repository: git fetch
116-
Local Repository->>+Working Tree:git checkout
116+
Local Repository->>+Working Tree:git restore
117117
Local Repository->>+Working Tree:git merge
118-
Remote Repository->>+Working Tree: git pull (shortcut for git fetch followed by git checkout/merge)
118+
Remote Repository->>+Working Tree: git pull (shortcut for git fetch followed by git merge)
119119
-->
120120

121121
<!--

episodes/16-verifying-code-style-linters.md

Lines changed: 106 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,19 @@ We can also use tools,
2727
called [**code linters**](https://en.wikipedia.org/wiki/Lint_%28software%29),
2828
to identify consistency issues in a report-style.
2929
Linters 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

3232
First, 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

4445
We 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,96 +85,142 @@ 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.
8795
We can look at a specific file (e.g. `inflammation-analysis.py`),
8896
or a package (e.g. `inflammation`).
8997
Let us look at our `inflammation` package and code inside it (namely `models.py` and `views.py`).
9098
From the project root do:
9199

92100
```bash
93-
$ pylint inflammation
101+
$ ruff check inflammation
94102
```
95103

96104
You 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

109120
Your own outputs of the above commands may vary depending on
110121
how you have implemented and fixed the code in previous exercises
111122
and 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` rules) and [isort](https://pypi.org/project/isort/) (`I` rules):
117144

118145
```bash
119-
$ pylint --long-help
146+
$ ruff check --select E,F,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+
I001 [*] Import block is un-sorted or un-formatted
153+
--> inflammation/views.py:3:1
154+
|
155+
1 | """Module containing code for plotting inflammation data."""
156+
2 |
157+
3 | / from matplotlib import pyplot as plt
158+
4 | | import numpy as np
159+
| |__________________^
160+
|
161+
help: Organize imports
162+
163+
F401 [*] `numpy` imported but unused
164+
--> inflammation/views.py:4:17
165+
|
166+
3 | from matplotlib import pyplot as plt
167+
4 | import numpy as np
168+
| ^^
169+
|
170+
help: Remove unused import: `numpy`
171+
172+
Found 2 errors.
173+
[*] 2 fixable with the `--fix` option.
135174
```
136175

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
176+
It is important to note that while tools such as Ruff are great at giving you
141177
a starting point to consider how to improve your code,
142178
they will not find everything that may be wrong with it.
143179

144-
::::::::::::::::::::::::::::::::::::::::: callout
180+
::::::::::::::::::::::::::::::::::::::: challenge
145181

146-
## How Does Pylint Calculate the Score?
182+
## Exercise: Add Ruff configurations to the `pyproject.toml` file
147183

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):
184+
You can define the Ruff configuration for a project by adding a section to the
185+
`pyproject.toml` file. For instance, you can define the set of rules to be checked
186+
for your codebase. Following [the Ruff documentation](https://docs.astral.sh/ruff/linter/),
187+
add a section to the `pyproject.toml` to enable the `E`, `W`, `F`, `UP`, `A`, `B`, `SIM`,
188+
and `I` rules for the project. Verify that the configuration is respected when running
189+
`ruff` (without the `--select` option):
151190

152191
```bash
153-
10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
192+
$ ruff check inflammation
193+
```
194+
195+
:::::::::::::::::::::::::::::::: solution
196+
197+
Add the following section to the `pyproject.toml`:
198+
199+
```toml
200+
[tool.ruff.lint]
201+
select = ["E", "W", "F", "UP", "A", "B", "SIM", "I"]
154202
```
155203

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!
204+
Running `ruff check inflammation` should indeed show problems with some of
205+
the `W` and `I` rules, which are not enabled with the default Ruff settings.
160206

207+
::::::::::::::::::::::::::::::::::::::::::
161208

162209
::::::::::::::::::::::::::::::::::::::::::::::::::
163210

164211
::::::::::::::::::::::::::::::::::::::: challenge
165212

166213
## Exercise: Further Improve Code Style of Our Project
167214

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.
215+
Select and fix a few of the issues with our code that Ruff detected.
216+
You can try using the Ruff's `--fix` command-line option to automatically fix
217+
(some of) the issues. If you manually edit the code, make sure you do not break
218+
the rest of the code in the process and that the code still runs.
219+
After making any changes, run Ruff again to verify you have resolved these issues.
171220

172221
::::::::::::::::::::::::::::::::::::::::::::::::::
173222

174-
Make sure you commit and push `requirements.txt`
223+
Make sure you commit and push `requirements.txt`, `pyproject.toml`,
175224
and any file with further code style improvements you did on to `style-fixes` branch and then
176225
merge all these changes into your development branch.
177226

@@ -184,8 +233,8 @@ with GitHub Actions - we will come back to automated linting in the episode on
184233
["Diagnosing Issues and Improving Robustness"](24-diagnosing-issues-improving-robustness.md).
185234

186235
```bash
187-
$ git add requirements.txt
188-
$ git commit -m "Added Pylint library"
236+
$ git add requirements.txt pyproject.toml
237+
$ git commit -m "Added Ruff library"
189238
$ git push origin style-fixes
190239
$ git switch develop
191240
$ git merge style-fixes
@@ -197,17 +246,16 @@ $ git push origin develop
197246
## Optional Exercise: Improve Code Style of Your Other Python Projects
198247

199248
If 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-
249+
run it past Ruff to see what issues with your code are detected, if any.
202250

203251
::::::::::::::::::::::::::::::::::::::::::::::::::
204252

205253
::: challenge
206254

207-
## Optional Exercise: More on Pylint
255+
## Optional Exercise: More on Ruff
208256

209257
Checkout [this optional exercise](17-section1-optional-exercises.md)
210-
to learn more about `pylint`.
258+
to learn more about `ruff`.
211259

212260
:::
213261

0 commit comments

Comments
 (0)