This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: asyncio.sleep() does not adhere to time.sleep() behavior for negative numbers
Type: behavior Stage: resolved
Components: asyncio Versions: Python 3.9
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: Marco Sulla, asvetlov, yselivanov
Priority: normal Keywords:

Created on 2020-02-20 11:44 by Marco Sulla, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (7)
msg362314 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-20 11:44
Python 3.9.0a3+ (heads/master-dirty:f2ee21d858, Feb 19 2020, 23:19:22) 
[GCC 9.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.sleep(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: sleep length must be non-negative
>>> import asyncio
>>> async def f():
...     await asyncio.sleep(-1)
...     print("no exception")
... 
>>> asyncio.run(f())
no exception

I think that also `asyncio.sleep()` should raise `ValueError` if the argument is less than zero.
msg362321 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2020-02-20 14:23
The ship has sailed, this change breaks a lot of existing code without a strong reason.
I recall very many cases in third-party libraries and commercial applications where a negative argument for asyncio.sleep() is processed as asyncio.sleep(0) without failure.
msg362345 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2020-02-20 19:17
> The ship has sailed, this change breaks a lot of existing code without a strong reason.

Yes.

It's a common thing to compute asyncio.sleep delay and sometimes it goes negative. The current behavior is part of our API now.
msg362349 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-20 20:52
> I recall very many cases in third-party libraries and commercial applications

Source?
msg362519 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-23 16:00
I see that many breaking changes was done in recent releases. I get only the ones for `asyncio` in Python 3.8:

https://bugs.python.org/issue36921
https://bugs.python.org/issue36373
https://bugs.python.org/issue34790
https://bugs.python.org/issue32528
https://bugs.python.org/issue34687
https://bugs.python.org/issue32314

So I suppose the ship isn't sailed yet.


Passing a negative number to a function that should sleep the task for x seconds is a mistake. And mistakes should never pass silently.

Furthermore, coherence matters. It's really confusing that two functions in two builtin modules that are quite identical have a different behavior.

IMHO, deprecating and then removing support for negative argument in `asyncio.sleep()` is very much less breaking compared to issues #36921 and #36373 .
msg362673 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2020-02-25 23:58
> Source?

I could not find a good source, sorry. I remember I had a complaint in uvloop to support negative timeouts, but I can't trace it. 

That said, I also distinctly remember seeing code (and writing such code myself) that performs computation on timeouts and does not care if the end value goes below 0.  It might be a weak data point but it's still a valid one.

> IMHO, deprecating and then removing support for negative argument in `asyncio.sleep()` is very much less breaking compared to issues #36921 and #36373 .

Breaking code/APIs always has a price and we always try to have a very good explanation "why" we want to bother ourselves and users to break backwards compat.  This one is not worth it IMHO.

We have more breaking API changes that are more substantial coming in future versions of asyncio. So I try to limit the impact by only breaking what's really necessary.
msg362724 - (view) Author: Marco Sulla (Marco Sulla) * Date: 2020-02-26 19:46
> I also distinctly remember seeing code (and writing such code myself) that performs computation on timeouts and does not care if the end value goes below 0.

This is not a good statistics. Frankly we can't measure the impact of the change from these considerations. And furthermore, `asyncio.sleep()` is used often, testing and mocking apart? I doubt it.

> we always try to have a very good explanation "why" we want to bother ourselves and users to break backwards compat.

Coherence and unhide mistakes are *very* strong points.

That said, I'm not so much interested in practice. Do as you wish. The problem is I always considered Python a very elegant programming language, and this behavior is not elegant at all. But, hey, amen.
History
Date User Action Args
2022-04-11 14:59:26adminsetgithub: 83879
2020-02-26 19:46:37Marco Sullasetresolution: not a bug -> rejected
2020-02-26 19:46:12Marco Sullasetmessages: + msg362724
2020-02-25 23:58:20yselivanovsetmessages: + msg362673
2020-02-23 16:00:04Marco Sullasettype: behavior
messages: + msg362519
2020-02-20 20:52:40Marco Sullasetmessages: + msg362349
2020-02-20 19:17:33yselivanovsetstatus: open -> closed
resolution: not a bug
messages: + msg362345

stage: resolved
2020-02-20 14:23:47asvetlovsetmessages: + msg362321
2020-02-20 11:44:23Marco Sullacreate