Skip to content

Commit 59a9207

Browse files
committed
Cancellable tasks no longer get task_id as an arg.
1 parent f9a9830 commit 59a9207

File tree

4 files changed

+62
-66
lines changed

4 files changed

+62
-66
lines changed

PRIMITIVES.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -360,21 +360,20 @@ async def comms(): # Perform some communications task
360360
# with known initial state on next pass.
361361
```
362362

363-
A `Cancellable` task is declared with the `@cancellable` decorator. When
364-
scheduled it will receive an initial arg which is a `TaskId` instance followed
365-
by any user-defined args. The `TaskId` instance is normally ignored however it
366-
can be useful for debugging - task_id() produces a unique integer task ID.
363+
A `Cancellable` task is declared with the `@cancellable` decorator:
367364

368365
```python
369366
@cancellable
370-
async def print_nums(_, num): # Discard task_id
367+
async def print_nums(num):
371368
while True:
372369
print(num)
373370
num += 1
374371
await sleep(1) # asyn.sleep() allows fast response to exception
375372
```
376373

377-
`Cancellable` tasks may be awaited or placed on the event loop:
374+
Positional or keyword arguments for the task are passed to the `Cancellable`
375+
constructor as below. Note that the coro is passed not using function call
376+
syntax. `Cancellable` tasks may be awaited or placed on the event loop:
378377

379378
```python
380379
await Cancellable(print_nums, 5) # single arg to print_nums.
@@ -436,7 +435,7 @@ exception to perform custom cleanup operations. This may be done as below:
436435

437436
```python
438437
@cancellable
439-
async def foo(task_id, arg):
438+
async def foo():
440439
while True:
441440
try:
442441
await sleep(1) # Main body of task
@@ -450,8 +449,7 @@ cancelled.
450449

451450
```python
452451
@cancellable
453-
async def bar(task_id):
454-
task_no = task_id() # Retrieve task no. from TaskId instance
452+
async def bar():
455453
try:
456454
await sleep(1) # Main body of task
457455
except StopTask:
@@ -469,19 +467,17 @@ name may outlive the task: a coro may end but the class enables its state to be
469467
checked. It is a subclass of `Cancellable` and its constructor disallows
470468
duplicate names: each instance of a coro must be assigned a unique name.
471469

472-
A `NamedTask` coro is defined with the `@cancellable` decorator. When scheduled
473-
it will receive an initial arg which is a `TaskId` instance followed by any
474-
user-defined args. Normally the `task_id` is ignored as per `Cancellable`.
470+
A `NamedTask` coro is defined with the `@cancellable` decorator.
475471

476472
```python
477473
@cancellable
478-
async def foo(_, arg1, arg2):
474+
async def foo(arg1, arg2):
479475
await asyn.sleep(1)
480476
print('Task foo has ended.', arg1, arg2)
481477
```
482478

483-
The `NamedTask` constructor takes the name, the coro, plus any user args. The
484-
resultant instance can be scheduled in the usual ways:
479+
The `NamedTask` constructor takes the name, the coro, plus any user positional
480+
or keyword args. Th eresultant instance can be scheduled in the usual ways:
485481

486482
```python
487483
await NamedTask('my foo', foo, 1, 2) # Pause until complete or killed
@@ -492,7 +488,7 @@ loop.create_task(NamedTask('my nums', foo, 10, 11)()) # Note () syntax.
492488
Cancellation is performed with:
493489

494490
```python
495-
await NamedTask.cancel('my foo') # API change
491+
await NamedTask.cancel('my foo')
496492
```
497493

498494
When cancelling a task there is no need to check if the task is still running:
@@ -557,7 +553,7 @@ The coro should have the following form:
557553

558554
```python
559555
@cancellable
560-
async def foo(task_id):
556+
async def foo():
561557
try:
562558
await asyncio.sleep(1) # User code here
563559
except StopTask:
@@ -573,7 +569,8 @@ is to simplify the code and to ensure accuracy of the `is_running` method. The
573569
latest API changes are:
574570
* `Cancellable.stopped()` is no longer a public method.
575571
* `NamedTask.cancel()` is now asynchronous.
576-
* `NamedTask` coros now receive a `TaskId` instance as their 1st arg.
572+
* `NamedTask` and `Cancellable` coros no longer receive a `TaskId` instance as
573+
their 1st arg.
577574
* `@namedtask` still works but is now an alias for `@cancellable`.
578575

579576
The drive to simplify code comes from the fact that `uasyncio` is itself under

asyn.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,13 @@ def __await__(self):
328328

329329
def cancellable(f):
330330
def new_gen(*args, **kwargs):
331-
g = f(*args, **kwargs)
332-
# Task ID is args[1] if a bound method (else args[0])
333-
idx = 0 if isinstance(args[0], TaskId) else 1
334-
task_id = args[idx]
331+
if isinstance(args[0], TaskId): # Not a bound method
332+
task_id = args[0]
333+
g = f(*args[1:], **kwargs)
334+
else: # Task ID is args[1] if a bound method
335+
task_id = args[1]
336+
args = (args[0],) + args[2:]
337+
g = f(*args, **kwargs)
335338
try:
336339
res = await g
337340
return res

asyn_demos.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ def print_tests():
4242

4343
# Cancellable task minimal example
4444
@asyn.cancellable
45-
async def print_nums(_, num):
45+
async def print_nums(num):
4646
while True:
4747
print(num)
4848
num += 1
4949
await asyn.sleep(1)
5050

5151
@asyn.cancellable
52-
async def add_one(_, num):
52+
async def add_one(num):
5353
num += 1
5454
await asyn.sleep(1)
5555
return num
@@ -70,14 +70,14 @@ def cancel_test():
7070
# NamedTask minimal example
7171

7272
@asyn.cancellable
73-
async def print_nums_named(_, num):
73+
async def print_nums_named(num):
7474
while True:
7575
print(num)
7676
num += 1
7777
await asyn.sleep(1)
7878

7979
@asyn.cancellable
80-
async def add_one_named(_, num):
80+
async def add_one_named(num):
8181
num += 1
8282
await asyn.sleep(1)
8383
return num
@@ -114,13 +114,13 @@ async def start(self, loop):
114114
print('Done')
115115

116116
@asyn.cancellable
117-
async def foo(self, _, arg):
117+
async def foo(self, arg):
118118
while True:
119119
await asyn.sleep(1)
120120
print('foo running, arg', arg)
121121

122122
@asyn.cancellable
123-
async def bar(self, _, arg):
123+
async def bar(self, arg):
124124
while True:
125125
await asyn.sleep(1)
126126
print('bar running, arg', arg)

cantest.py

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def printexp(exp, runtime=0):
5656
# cancel_test1()
5757

5858
@asyn.cancellable
59-
async def foo(task_id, num):
59+
async def foo(num):
6060
try:
6161
await asyncio.sleep(4)
6262
except asyn.StopTask:
@@ -109,7 +109,7 @@ async def forever(n):
109109

110110
# Intercepting the StopTask exception.
111111
@asyn.cancellable
112-
async def rats(task_id, n):
112+
async def rats(n):
113113
try:
114114
await forever(n)
115115
except asyn.StopTask:
@@ -147,7 +147,7 @@ def test2():
147147

148148
# Intercepting the StopTask exception.
149149
@asyn.cancellable
150-
async def cant3(task_id):
150+
async def cant3():
151151
try:
152152
await asyncio.sleep(1)
153153
print('Task cant3 has ended.')
@@ -187,51 +187,48 @@ def test3():
187187
# task_id automatically
188188

189189
@asyn.cancellable
190-
async def cant40(task_id):
191-
task_no = task_id()
190+
async def cant40(num):
192191
while True:
193192
try:
194193
await asyn.sleep(1)
195-
print('Task cant40 no. {} running.'.format(task_no))
194+
print('Task cant40 no. {} running.'.format(num))
196195
except asyn.StopTask:
197-
print('Task cant40 no. {} was cancelled'.format(task_no))
196+
print('Task cant40 no. {} was cancelled'.format(num))
198197
return
199198

200199
@asyn.cancellable
201-
async def cant41(task_id, arg=0):
202-
task_no = task_id()
200+
async def cant41(num, arg=0):
203201
try:
204202
await asyn.sleep(1)
205-
print('Task cant41 no. {} running, arg {}.'.format(task_no, arg))
203+
print('Task cant41 no. {} running, arg {}.'.format(num, arg))
206204
except asyn.StopTask:
207-
print('Task cant41 no. {} was cancelled.'.format(task_no))
205+
print('Task cant41 no. {} was cancelled.'.format(num))
208206
return
209207
else:
210-
print('Task cant41 no. {} ended.'.format(task_no))
208+
print('Task cant41 no. {} ended.'.format(num))
211209

212-
async def cant42(task_no):
210+
async def cant42(num):
213211
while True:
214-
print('Task cant42 no. {} running'.format(task_no))
212+
print('Task cant42 no. {} running'.format(num))
215213
await asyn.sleep(1.2)
216214

217215
# Test await syntax and throwing exception to subtask
218216
@asyn.cancellable
219-
async def chained(task_id, x, y, *, red, blue):
217+
async def chained(num, x, y, *, red, blue):
220218
print('Args:', x, y, red, blue) # Test args and kwargs
221-
task_no = task_id()
222219
try:
223-
await cant42(task_no)
220+
await cant42(num)
224221
except asyn.StopTask:
225-
print('Task chained no. {} was cancelled'.format(task_no))
222+
print('Task chained no. {} was cancelled'.format(num))
226223

227224
async def run_cancel_test4():
228-
await asyn.Cancellable(cant41, 5)
225+
await asyn.Cancellable(cant41, 0)
229226
loop = asyncio.get_event_loop()
230-
loop.create_task(asyn.Cancellable(cant40)()) # 3 instances in default group 0
231-
loop.create_task(asyn.Cancellable(cant40)())
232-
loop.create_task(asyn.Cancellable(cant40)())
233-
loop.create_task(asyn.Cancellable(chained, 1, 2, red=3, blue=4, group=1)())
234-
loop.create_task(asyn.Cancellable(cant41)()) # Runs to completion
227+
loop.create_task(asyn.Cancellable(cant40, 1)()) # 3 instances in default group 0
228+
loop.create_task(asyn.Cancellable(cant40, 2)())
229+
loop.create_task(asyn.Cancellable(cant40, 3)())
230+
loop.create_task(asyn.Cancellable(chained, 4, 1, 2, red=3, blue=4, group=1)())
231+
loop.create_task(asyn.Cancellable(cant41, 5)()) # Runs to completion
235232
print('Running tasks')
236233
await asyncio.sleep(3)
237234
print('About to cancel group 0 tasks')
@@ -288,7 +285,7 @@ async def start(self, loop):
288285
print('Done')
289286

290287
@asyn.cancellable
291-
async def foo(self, _, arg):
288+
async def foo(self, arg):
292289
try:
293290
while True:
294291
await asyn.sleep(1)
@@ -297,7 +294,7 @@ async def foo(self, _, arg):
297294
print('foo was cancelled')
298295

299296
@asyn.cancellable
300-
async def bar(self, _, arg, *, x=1, y=2):
297+
async def bar(self, arg, *, x=1, y=2):
301298
try:
302299
while True:
303300
await asyn.sleep(1)
@@ -334,20 +331,19 @@ def test5():
334331

335332
# test 6: test NamedTask.is_running()
336333
@asyn.cancellable
337-
async def cant60(task_id, name):
338-
task_no = task_id()
339-
print('Task cant60 no. {} name \"{}\" running.'.format(task_no, name))
334+
async def cant60(name):
335+
print('Task cant60 name \"{}\" running.'.format(name))
340336
try:
341337
for _ in range(5):
342338
await asyncio.sleep(2) # 2 secs latency.
343339
except asyn.StopTask:
344-
print('Task cant60 no. {} name \"{}\" was cancelled.'.format(task_no, name))
340+
print('Task cant60 name \"{}\" was cancelled.'.format(name))
345341
return
346342
else:
347-
print('Task cant60 no. {} name \"{}\" ended.'.format(task_no, name))
343+
print('Task cant60 name \"{}\" ended.'.format(name))
348344

349345
@asyn.cancellable
350-
async def cant61(task_id):
346+
async def cant61():
351347
try:
352348
while True:
353349
for name in ('complete', 'cancel me'):
@@ -378,8 +374,8 @@ async def run_cancel_test6(loop):
378374

379375

380376
def test6():
381-
printexp('''Task cant60 no. 0 name "complete" running.
382-
Task cant60 no. 1 name "cancel me" running.
377+
printexp('''Task cant60 name "complete" running.
378+
Task cant60 name "cancel me" running.
383379
Task "complete" running: True
384380
Task "cancel me" running: True
385381
Task "complete" running: True
@@ -393,7 +389,7 @@ def test6():
393389
Cancelling task "cancel me". 1.5 secs latency.
394390
Task "complete" running: True
395391
Task "cancel me" running: True
396-
Task cant60 no. 1 name "cancel me" was cancelled.
392+
Task cant60 name "cancel me" was cancelled.
397393
Task "complete" running: True
398394
Task "cancel me" running: False
399395
Task "complete" running: True
@@ -402,18 +398,18 @@ def test6():
402398
Task "cancel me" running: False
403399
Task "complete" running: True
404400
Task "cancel me" running: False
405-
Task cant60 no. 0 name "complete" ended.
401+
Task cant60 name "complete" ended.
406402
Task "complete" running: False
407403
Task "cancel me" running: False
408404
Task "complete" running: False
409405
Task "cancel me" running: False
410-
Task cant60 no. 3 name "cancel wait" running.
406+
Task cant60 name "cancel wait" running.
411407
Cancelling task "cancel wait". 1.5 secs latency.
412408
Task "complete" running: False
413409
Task "cancel me" running: False
414410
Task "complete" running: False
415411
Task "cancel me" running: False
416-
Task cant60 no. 3 name "cancel wait" was cancelled.
412+
Task cant60 name "cancel wait" was cancelled.
417413
Was cancelled in 1503 ms
418414
Cancelling cant61
419415
Task cant61 cancelled.

0 commit comments

Comments
 (0)