I had an issue with my code where I called Task.cancel on an instance and it would stay in state pending (cancelled returning False). I did some digging and found in the source that Task overwrites the cancel method and does not directly set the new state. Going back to the documentation, I did not find anything that documents this behavior.
The problematic use case was a situation like the following: I iterate over a list of tasks, check various properties (like how long they are running etc.) and based on that decide to either give it more time or cancel it or check its results if its done. After having handled all running tasks, I do other work and later return to check them again. When I checked again, I explicitly checked the case where I already had cancelled a task. In this next iteration I want to see if it is done yet or if it needs some more time cleaning up. However, to my surprise, task.cancelled() returned false, which led me to execute task.cancel() again, which in turn raised a CancellationError inside the finally-block doing cleanup. I then added something like this: task.cancel() assert task.canelled() A statement that, on a future, has to succeed (as I see it from the source) but on a task must fail. Is there a reason this behavior is not documented or did I miss it somewhere? Also since this seems to be desired behavior, is there a reliable way to perform this check on a task? In __repr__ you check against _must_cancel for the difference between displaying "PENDING" and "CANCELLING" (this actually led me to the point of looking at the Task source). However, this is an internal variable and so I probably shouldn't use it. The only other thing I can come up with is using the return value and store it somewhere else and then check that variable, however that seems rather "dirty", storing a value that should belong to the task outside of it.
