Skip to content

Commit e776d1d

Browse files
committed
Update release notes
Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 25be221 commit e776d1d

File tree

1 file changed

+42
-44
lines changed

1 file changed

+42
-44
lines changed

RELEASE_NOTES.md

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,62 @@
22

33
## Summary
44

5-
The minimum Python supported version was bumped to 3.11 and the `Select` class replaced by the new `Selector`.
5+
The minimum Python supported version was bumped to 3.11 and the `Select` class replaced by the new `select()` function.
66

77
## Upgrading
88

99
* The minimum supported Python version was bumped to 3.11, downstream projects will need to upgrade too to use this version.
1010

11-
* The `Select` class was replaced by a new `Selector` class, with the following improvements:
11+
* The `Select` class was replaced by a new `select()` function, with the following improvements:
1212

1313
* Type-safe: proper type hinting by using the new helper type guard `selected_from()`.
1414
* Fixes potential starvation issues.
1515
* Simplifies the interface by providing values one-by-one.
1616
* Guarantees there are no dangling tasks left behind when used as an async context manager.
1717

18-
This new class acts as an [async context manager](https://docs.python.org/3/reference/datamodel.html#async-context-managers) and an [async iterator](https://docs.python.org/3.11/library/collections.abc.html#collections.abc.AsyncIterator), and makes sure no dangling tasks are left behind after a select loop is done.
18+
This new function is an [async iterator](https://docs.python.org/3.11/library/collections.abc.html#collections.abc.AsyncIterator), and makes sure no dangling tasks are left behind after a select loop is done.
1919

2020
Example:
2121
```python
2222
timer1 = Timer.periodic(datetime.timedelta(seconds=1))
2323
timer2 = Timer.timeout(datetime.timedelta(seconds=0.5))
2424

25-
async with Selector(timer1, timer2) as selector:
26-
async for selected in selector:
27-
if selected_from(selected, timer1):
28-
# Beware: `selected.value` might raise an exception, you can always
29-
# check for exceptions with `selected.exception` first or use
30-
# a try-except block. You can also quickly check if the receiver was
31-
# stopped and let any other unexpected exceptions bubble up.
32-
if selected.was_stopped():
33-
print("timer1 was stopped")
34-
continue
35-
print(f"timer1: now={datetime.datetime.now()} drift={selected.value}")
36-
timer2.stop()
37-
elif selected_from(selected, timer2):
38-
# Explicitly handling of exceptions
39-
match selected.exception:
40-
case ReceiverStoppedError():
41-
print("timer2 was stopped")
42-
case Exception() as exception:
43-
print(f"timer2: exception={exception}")
44-
case None:
45-
# All good, no exception, we can use `selected.value` safely
46-
print(
47-
f"timer2: now={datetime.datetime.now()} "
48-
f"drift={selected.value}"
49-
)
50-
case _ as unhanded:
51-
assert_never(unhanded)
52-
else:
53-
# This is not necessary, as select() will check for exhaustiveness, but
54-
# it is good practice to have it in case you forgot to handle a new
55-
# receiver added to `select()` at a later point in time.
56-
assert False
25+
async for selected in selector(timer1, timer2):
26+
if selected_from(selected, timer1):
27+
# Beware: `selected.value` might raise an exception, you can always
28+
# check for exceptions with `selected.exception` first or use
29+
# a try-except block. You can also quickly check if the receiver was
30+
# stopped and let any other unexpected exceptions bubble up.
31+
if selected.was_stopped():
32+
print("timer1 was stopped")
33+
continue
34+
print(f"timer1: now={datetime.datetime.now()} drift={selected.value}")
35+
timer2.stop()
36+
elif selected_from(selected, timer2):
37+
# Explicitly handling of exceptions
38+
match selected.exception:
39+
case ReceiverStoppedError():
40+
print("timer2 was stopped")
41+
case Exception() as exception:
42+
print(f"timer2: exception={exception}")
43+
case None:
44+
# All good, no exception, we can use `selected.value` safely
45+
print(
46+
f"timer2: now={datetime.datetime.now()} "
47+
f"drift={selected.value}"
48+
)
49+
case _ as unhanded:
50+
assert_never(unhanded)
51+
else:
52+
# This is not necessary, as select() will check for exhaustiveness, but
53+
# it is good practice to have it in case you forgot to handle a new
54+
# receiver added to `select()` at a later point in time.
55+
assert False
5756
```
5857

5958
## New Features
6059

61-
* A new `Selector` class was added, please look at the *Upgrading* section for details.
60+
* A new `select()` function was added, please look at the *Upgrading* section for details.
6261

6362
* A new `Event` utility receiver was added.
6463

@@ -80,14 +79,13 @@ The minimum Python supported version was bumped to 3.11 and the `Select` class r
8079

8180
asyncio.ensure_future(exit_after_10_seconds())
8281

83-
async with Selector(exit_event, other_receiver) as selector:
84-
async for selected in selector:
85-
if selected_from(selected, exit_event):
86-
break
87-
if selected_from(selected, other_receiver):
88-
print(selected.value)
89-
else:
90-
assert False, "Unknow receiver selected"
82+
async for selected in selector(exit_event, other_receiver):
83+
if selected_from(selected, exit_event):
84+
break
85+
if selected_from(selected, other_receiver):
86+
print(selected.value)
87+
else:
88+
assert False, "Unknow receiver selected"
9189
```
9290

9391
* The `Timer` class now has more descriptive `__str__` and `__repr__` methods.

0 commit comments

Comments
 (0)