Skip to content

Commit 66f13a7

Browse files
authored
Python 3.11 materials: Move all code to scripts (#288)
* Move all code to scripts * Revert to *Ts syntax, since it's supported in latest version of Black
1 parent 33b2e16 commit 66f13a7

File tree

12 files changed

+140
-79
lines changed

12 files changed

+140
-79
lines changed

python-311/README.md

Lines changed: 61 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,27 @@ You'll find examples from all these tutorials in this repository.
1818

1919
## Dependencies
2020

21-
Install necessary dependencies for the examples:
21+
Create and activate a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/):
2222

2323
```console
24-
$ python -m pip install colorama parse
24+
$ python -m venv venv
25+
$ source venv/bin/activate
2526
```
2627

28+
Install necessary dependencies for the examples (see [`requirements.in`](requirements.in)):
29+
30+
```console
31+
(venv) $ python -m pip install colorama parse
32+
```
33+
34+
Alternatively, you can install dependencies from [`requirements.txt`](requirements.txt) if you want to ensure that you're using the same versions of the third-party packages:
35+
36+
```console
37+
(venv) $ python -m pip install -r requirements.txt
38+
```
39+
40+
These examples have been run with [Python 3.11.0rc1](https://www.python.org/downloads/release/python-3110rc1/), the first release candidate of Python 3.11.
41+
2742
## Examples
2843

2944
This section only contains brief instructions on how you can run the examples. See the tutorials for technical details.
@@ -33,7 +48,7 @@ This section only contains brief instructions on how you can run the examples. S
3348
Load [`scientists.py`](scientists.py) into your interactive REPL:
3449

3550
```console
36-
$ python -i scientists.py
51+
(venv) $ python -i scientists.py
3752
```
3853
You can then experiment with `dict_to_person()` and `convert_pair()`:
3954

@@ -64,17 +79,12 @@ See [Even Better Error Messages in Python 3.11](https://realpython.com/python311
6479

6580
Use `ExceptionGroup` and `except*` to handle several errors at once:
6681

67-
```pycon
68-
>>> try:
69-
... raise ExceptionGroup(
70-
... "group", [TypeError("str"), ValueError(654), TypeError("int")]
71-
... )
72-
... except* ValueError as eg:
73-
... print(f"Handling ValueErrors: {eg.exceptions}")
74-
...
82+
```console
83+
(venv) $ python exception_group.py
7584
Handling ValueErrors: (ValueError(654),)
7685
+ Exception Group Traceback (most recent call last):
77-
| ...
86+
| File "/home/realpython/exception_group.py", line 2, in <module>
87+
| raise ExceptionGroup(
7888
| ExceptionGroup: group (2 sub-exceptions)
7989
+-+---------------- 1 ----------------
8090
| TypeError: str
@@ -90,7 +100,7 @@ See [Exception Groups and `except*` in Python 3.11](https://realpython.com/pytho
90100
Run [`count.py`](count.py), [`count_gather.py`](count_gather.py), and [`count_taskgroup.py`](count_taskgroup.py) and compare their behaviors. For example:
91101

92102
```console
93-
$ python count_taskgroup.py scientists.py rot13.txt count.py
103+
(venv) $ python count_taskgroup.py scientists.py rot13.txt count.py
94104
scientists.py □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ (44)
95105
Files with thirteen lines are too scary!
96106
count.py □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ (32)
@@ -105,7 +115,7 @@ See [Asynchronous Task Groups in Python 3.11](https://realpython.com/python311-e
105115
Use [`read_toml.py`](read_toml.py) to read them:
106116

107117
```console
108-
$ python read_toml.py python_info.toml tomli_pyproject.toml
118+
(venv) $ python read_toml.py python_info.toml tomli_pyproject.toml
109119
======================python_info.toml======================
110120
{'python': {'version': 3.11,
111121
'release_manager': 'Pablo Galindo Salgado',
@@ -126,19 +136,15 @@ $ python read_toml.py python_info.toml tomli_pyproject.toml
126136
'PyPI': 'https://pypi.org/project/tomli'}}}
127137
```
128138

129-
[`tomllib_w.py`](tomllib_w.py) shows how you can write simplified TOML files:
139+
You can use [`tomllib_w.py`](tomllib_w.py) to write simplified TOML files. [`write_toml.py`](write_toml.py) demonstrates how you can use it:
130140

131-
```pycon
132-
>>> import tomllib_w
133-
>>> data = {"url": "https://realpython.com/python311-tomllib/",
134-
... "author": {"name": "Geir Arne Hjelle", "email": "[email protected]"}}
135-
136-
>>> print(tomllib_w.dumps(data))
141+
```console
142+
(venv) $ python write_toml.py
137143
url = "https://realpython.com/python311-tomllib/"
138144

139145
[author]
140146
name = "Geir Arne Hjelle"
141-
email = "geirarne@realypython.com"
147+
email = "geirarne@realpython.com"
142148
```
143149

144150
See [`tomllib` TOML Parser in Python 3.11](https://realpython.com/python311-tomllib/#tomllib-toml-parser-in-python-311) and [PEP 680](https://peps.python.org/pep-0680/).
@@ -148,7 +154,7 @@ See [`tomllib` TOML Parser in Python 3.11](https://realpython.com/python311-toml
148154
[`polar_point.py`](polar_point.py) uses `Self` for annotation:
149155

150156
```console
151-
$ python polar_point.py
157+
(venv) $ python polar_point.py
152158
PolarPoint(r=5.0, φ=0.9272952180016122)
153159
```
154160

@@ -159,7 +165,7 @@ See [`Self` Type](https://realpython.com/python311-tomllib/#self-type) and [PEP
159165
[`execute_sql.py`](execute_sql.py) shows an example of `LiteralString`:
160166

161167
```console
162-
$ python execute_sql.py
168+
(venv) $ python execute_sql.py
163169
Pretending to execute: SELECT * FROM users
164170
Pretending to execute: SELECT * FROM users
165171

@@ -179,22 +185,18 @@ See [Variadic Generic Types](https://realpython.com/python311-tomllib/#variadic-
179185

180186
Use `.add_notes()` to annotate exceptions with custom notes:
181187

182-
```pycon
183-
>>> err = ValueError(678)
184-
>>> err.add_note("Enriching Exceptions with Notes")
185-
>>> err.add_note("Python 3.11")
186-
187-
>>> err.__notes__
188-
['Enriching Exceptions with Notes', 'Python 3.11']
189-
>>> for note in err.__notes__:
190-
... print(note)
191-
...
188+
```console
189+
(venv) $ python exception_notes.py
190+
err.__notes__ = ['Enriching Exceptions with Notes', 'Python 3.11']
191+
192+
--------------------- Loop over notes ----------------------
192193
Enriching Exceptions with Notes
193194
Python 3.11
194195

195-
>>> raise err
196+
--------------- Notes are added to traceback ---------------
196197
Traceback (most recent call last):
197-
...
198+
File "/home/realpython/exception_notes.py", line 12, in <module>
199+
raise err
198200
ValueError: 678
199201
Enriching Exceptions with Notes
200202
Python 3.11
@@ -206,14 +208,9 @@ See [Annotate Exceptions With Custom Notes](https://realpython.com/python311-exc
206208

207209
You can use `sys.exception()` to access the active exception:
208210

209-
```pycon
210-
>>> import sys
211-
212-
>>> try:
213-
... raise ValueError("bpo-46328")
214-
... except ValueError:
215-
... print(f"Handling {sys.exception()}")
216-
...
211+
```console
212+
(venv) $ python active_exception.py
213+
Handling bpo-46328
217214
Handling bpo-46328
218215
```
219216

@@ -226,7 +223,7 @@ See [Reference the Active Exception With `sys.exception()`](https://realpython.c
226223
`traceback_demo.py` shows that tracebacks can be consistently accessed through the exception object:
227224

228225
```console
229-
$ python traceback_demo.py
226+
(venv) $ python traceback_demo.py
230227
tb_last(exc_value.__traceback__) = 'bad_calculation:13'
231228
tb_last(exc_tb) = 'bad_calculation:13'
232229
```
@@ -237,30 +234,20 @@ See [Reference the Active Traceback Consistently](https://realpython.com/python3
237234

238235
You can use `math.cbrt()` to calculate cube roots:
239236

240-
```pycon
241-
>>> import math
242-
>>> math.cbrt(729)
243-
9.000000000000002
244-
245-
>>> 729**(1/3)
246-
8.999999999999998
247-
248-
>>> math.pow(729, 1/3)
249-
8.999999999999998
237+
```console
238+
(venv) $ python cube_root.py
239+
math.cbrt(729) = 9.000000000000002
240+
729 ** (1 / 3) = 8.999999999999998
241+
math.pow(729, 1 / 3) = 8.999999999999998
250242
```
251243

252244
You can use `math.exp2()` to calculate powers of two:
253245

254-
```pycon
255-
>>> import math
256-
>>> math.exp2(16)
257-
65536.0
258-
259-
>>> 2**16
260-
65536
261-
262-
>>> math.pow(2, 16)
263-
65536.0
246+
```console
247+
(venv) $ python power_of_two.py
248+
math.exp2(16) = 65536.0
249+
2**16 = 65536
250+
math.pow(2, 16) = 65536.0
264251
```
265252

266253
See [Cube Roots and Powers of Two](https://realpython.com/python311-error-messages/#cube-roots-and-powers-of-two), [BPO 44357](https://github.com/python/cpython/issues/88523) and [BPO 45917](https://github.com/python/cpython/issues/90075).
@@ -269,10 +256,9 @@ See [Cube Roots and Powers of Two](https://realpython.com/python311-error-messag
269256

270257
You can use underscores when defining fractions from strings:
271258

272-
```pycon
273-
>>> from fractions import Fraction
274-
>>> print(Fraction("6_024/1_729"))
275-
6024/1729
259+
```console
260+
(venv) $ python underscore.py
261+
Fraction('6_024/1_729') = 6024/1729
276262
```
277263

278264
See [Underscores in Fractions](https://realpython.com/python311-error-messages/#underscores-in-fractions) and [BPO 44258](https://github.com/python/cpython/issues/88424).
@@ -281,13 +267,12 @@ See [Underscores in Fractions](https://realpython.com/python311-error-messages/#
281267

282268
The Norwegian calculator implemented in [`kalkulator.py`](kalkulator.py) uses `operator.call()`:
283269

284-
```pycon
285-
>>> import kalkulator
286-
>>> kalkulator.calculate("20 pluss 22")
287-
42.0
288-
289-
>>> kalkulator.calculate("11 delt på 3")
290-
3.6666666666666665
270+
```console
271+
(venv) $ python kalkulator.py
272+
20 pluss 22 = 42.0
273+
2022 minus 1991 = 31.0
274+
45 ganger 45 = 2025.0
275+
11 delt på 3 = 3.6666666666666665
291276
```
292277

293278
See [Flexible Calling of Objects](https://realpython.com/python311-error-messages/#flexible-calling-of-objects) and [BPO 44019](https://github.com/python/cpython/issues/88185).

python-311/active_exception.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import sys
2+
3+
try:
4+
raise ValueError("bpo-46328")
5+
except ValueError:
6+
print(f"Handling {sys.exception()}")
7+
8+
# Typically you should prefer except ValueError as err:
9+
try:
10+
raise ValueError("bpo-46328")
11+
except ValueError as err:
12+
print(f"Handling {err}")

python-311/cube_root.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import math
2+
3+
print(f"{math.cbrt(729) = }")
4+
print(f"{729 ** (1 / 3) = }")
5+
print(f"{math.pow(729, 1 / 3) = }")

python-311/exception_group.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
try:
2+
raise ExceptionGroup(
3+
"group", [TypeError("str"), ValueError(654), TypeError("int")]
4+
)
5+
except* ValueError as eg:
6+
print(f"Handling ValueErrors: {eg.exceptions}")

python-311/exception_notes.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
err = ValueError(678)
2+
err.add_note("Enriching Exceptions with Notes")
3+
err.add_note("Python 3.11")
4+
5+
print(f"{err.__notes__ = }")
6+
7+
print("", " Loop over notes ".center(60, "-"), sep="\n")
8+
for note in err.__notes__:
9+
print(note)
10+
11+
print("", " Notes are added to traceback ".center(60, "-"), sep="\n")
12+
raise err

python-311/kalkulator.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,13 @@ def calculate(text):
1515
if (ops := EXPRESSION.parse(text)) and ops["operation"] in OPERATIONS:
1616
operation = OPERATIONS[ops["operation"]]
1717
return operator.call(operation, ops["operand1"], ops["operand2"])
18+
19+
20+
if __name__ == "__main__":
21+
for calculation in [
22+
"20 pluss 22",
23+
"2022 minus 1991",
24+
"45 ganger 45",
25+
"11 delt på 3",
26+
]:
27+
print(f"{calculation} = {calculate(calculation)}")

python-311/ndarray.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from typing import Generic, Literal, NewType, TypeVarTuple, Unpack
1+
from typing import Generic, Literal, NewType, TypeVarTuple
22

33
Ts = TypeVarTuple("Ts")
44

55

6-
class Array(Generic[Unpack[Ts]]): # You can use *Ts instead of Unpack[Ts]
7-
...
6+
class Array(Generic[*Ts]):
7+
... # Not implemented here
88

99

1010
Height = NewType("Height", int)

python-311/power_of_two.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import math
2+
3+
print(f"{math.exp2(16) = }")
4+
print(f"{2**16 = }")
5+
print(f"{math.pow(2, 16) = }")

python-311/requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
colorama
2+
parse

python-311/requirements.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# This file is autogenerated by pip-compile with python 3.11
3+
# To update, run:
4+
#
5+
# pip-compile requirements.in
6+
#
7+
colorama==0.4.5
8+
# via -r requirements.in
9+
parse==1.19.0
10+
# via -r requirements.in

0 commit comments

Comments
 (0)