How about adding msg argument to task.cancel()?
TL;DR:
def _on_timeout(self, task: "asyncio.Task[None]") -> None:
task.cancel(msg="timeout") # <--- add the reason of cancellation
self._state = _State.TIMEOUT
# drop the reference early
self._timeout_handler = None
This would be useful to distinguish the reason of cancellation in library's user programs.