Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for time.monotonic (and time.monotonic_ns) #369

Merged
merged 1 commit into from
Oct 2, 2020

Conversation

jmehnle
Copy link
Contributor

@jmehnle jmehnle commented Sep 30, 2020

There's a seemingly abandoned attempt at adding support for time.monotonic in #199. As there were major changes to freezegun since then, I decided to take a fresh stab at implementing such support. It's worth noting that time.monotonic doesn't give many guarantees to begin with, so not many are tested.

I'd be happy to add a few documentation bits if this implementation and the accompanying tests work for you.

@jmehnle jmehnle force-pushed the feature/time.monotonic branch from 399a7f8 to 05b6926 Compare September 30, 2020 21:00
@boxed
Copy link
Contributor

boxed commented Oct 1, 2020

Looks good to me! You feel comfortable with me merging?

@jmehnle jmehnle force-pushed the feature/time.monotonic branch from 05b6926 to 8938a69 Compare October 2, 2020 17:13
@jmehnle
Copy link
Contributor Author

jmehnle commented Oct 2, 2020

I added minimalistic documentation to README.rst. Good to merge!

@boxed boxed merged commit b9e15e2 into spulec:master Oct 2, 2020
@boxed
Copy link
Contributor

boxed commented Oct 2, 2020

Thanks!

@jmehnle
Copy link
Contributor Author

jmehnle commented Dec 23, 2020

Can we expect a new release, say, 1.0.1, any time soon?

@boxed
Copy link
Contributor

boxed commented Dec 23, 2020

@spulec ?

marcinsulikowski added a commit to marcinsulikowski/freezegun that referenced this pull request Sep 14, 2022
The following code:

    async def test():
        with freeze_time("2020-01-01"):
            await asyncio.sleep(0.01)

hangs forever since FreezeGun 1.1.0 because 1.1.0 started patching
`time.monotonic()` (see spulec#369) which is used internally by `asyncio`
event loops to schedule code for execution in the future. This breaks
many projects that uses FreezeGun to test asynchronous code.

We fix this by changing `freeze_time` to patch asyncio event loop's
`time()` method in a way that it uses real monotnic time instead of the
frozen one. Note that we couldn't achieve this by adding `asyncio` to
`DEFAULT_IGNORE_LIST` in `freezegun/config.py` because any running async
code has functions from the `asyncio` module on its stack -- adding
`asyncio` to the ignore list would just disable freezeing time in any
async code. This is why we patch one method of a specific class instead.

This change not only fixes `asyncio.sleep()` but also things like
`asyncio.get_running_loop().call_later` (for scheduling task execution
in the future) which in turn makes things like timeouts work in async
code while time is frozen. This may not be desired because some users
may expect that execution of events scheduled to happen in the future
can be controlled using FreezeGun. However, it's not easy to distinguish
between things that users would like to see frozen time and those which
should not (like `asyncio.sleep()`) because all of them use the same
clock. Therefore, we opt for making all `asyncio` internals not affected
by FreezeGun.

We also add more tests that verify how FreezeGun interacts with asyncio
code, including tests that cover the scenario described in spulec#401 which we
aim to fix.

Closes spulec#401
marcinsulikowski added a commit to marcinsulikowski/freezegun that referenced this pull request Sep 14, 2022
The following code:

    async def test():
        with freeze_time("2020-01-01"):
            await asyncio.sleep(0.01)

hangs forever since FreezeGun 1.1.0 because 1.1.0 started patching
`time.monotonic()` (see spulec#369) which is used internally by `asyncio`
event loops to schedule code for execution in the future. This breaks
many projects that uses FreezeGun to test asynchronous code.

We fix this by changing `freeze_time` to patch asyncio event loop's
`time()` method in a way that it uses real monotonic time instead of the
frozen one. Note that we couldn't achieve this by adding `asyncio` to
`DEFAULT_IGNORE_LIST` in `freezegun/config.py` because any running async
code has functions from the `asyncio` module on its stack -- adding
`asyncio` to the ignore list would just disable freezing time in any
async code. This is why we patch one method of a specific class instead.

This change not only fixes `asyncio.sleep()` but also things like
`asyncio.get_running_loop().call_later` (for scheduling task execution
in the future) which in turn makes things like timeouts work in async
code while time is frozen. This may not be desired because some users
may expect that execution of events scheduled to happen in the future
can be controlled using FreezeGun. However, it's not easy to distinguish
between things that users would like to see frozen time and those which
should not (like `asyncio.sleep()`) because all of them use the same
clock. Therefore, we opt for making all `asyncio` internals not affected
by FreezeGun.

We also add more tests that verify how FreezeGun interacts with asyncio
code, including tests that cover the scenario described in spulec#401 which we
aim to fix.

Closes spulec#401
marcinsulikowski added a commit to marcinsulikowski/freezegun that referenced this pull request Sep 14, 2022
The following code:

    async def test():
        with freeze_time("2020-01-01"):
            await asyncio.sleep(0.01)

hangs forever since FreezeGun 1.1.0 because 1.1.0 started patching
`time.monotonic()` (see spulec#369) which is used internally by `asyncio`
event loops to schedule code for execution in the future. This breaks
many projects that uses FreezeGun to test asynchronous code.

We fix this by changing `freeze_time` to patch asyncio event loop's
`time()` method in a way that it uses real monotonic time instead of the
frozen one. Note that we couldn't achieve this by adding `asyncio` to
`DEFAULT_IGNORE_LIST` in `freezegun/config.py` because any running async
code has functions from the `asyncio` module on its stack -- adding
`asyncio` to the ignore list would just disable freezing time in any
async code. This is why we patch one method of a specific class instead.

This change not only fixes `asyncio.sleep()` but also things like
`asyncio.get_running_loop().call_later` (for scheduling task execution
in the future) which in turn makes things like timeouts work in async
code while time is frozen. This may not be desired because some users
may expect that execution of events scheduled to happen in the future
can be controlled using FreezeGun. However, it's not easy to distinguish
between things that users would like to see frozen time and those which
should not (like `asyncio.sleep()`) because all of them use the same
clock. Therefore, we opt for making all `asyncio` internals not affected
by FreezeGun.

We also add more tests that verify how FreezeGun interacts with asyncio
code, including tests that cover the scenario described in spulec#437 which we
aim to fix.

Closes spulec#401
Closes spulec#437
marcinsulikowski added a commit to marcinsulikowski/freezegun that referenced this pull request Feb 20, 2023
The following code:

    async def test():
        with freeze_time("2020-01-01"):
            await asyncio.sleep(0.01)

hangs forever since FreezeGun 1.1.0 because 1.1.0 started patching
`time.monotonic()` (see spulec#369) which is used internally by `asyncio`
event loops to schedule code for execution in the future. This breaks
many projects that uses FreezeGun to test asynchronous code.

We fix this by changing `freeze_time` to patch asyncio event loop's
`time()` method in a way that it uses real monotonic time instead of the
frozen one. Note that we couldn't achieve this by adding `asyncio` to
`DEFAULT_IGNORE_LIST` in `freezegun/config.py` because any running async
code has functions from the `asyncio` module on its stack -- adding
`asyncio` to the ignore list would just disable freezing time in any
async code. This is why we patch one method of a specific class instead.

This change not only fixes `asyncio.sleep()` but also things like
`asyncio.get_running_loop().call_later` (for scheduling task execution
in the future) which in turn makes things like timeouts work in async
code while time is frozen. This may not be desired because some users
may expect that execution of events scheduled to happen in the future
can be controlled using FreezeGun. However, it's not easy to distinguish
between things that users would like to see frozen time and those which
should not (like `asyncio.sleep()`) because all of them use the same
clock. Therefore, we opt for making all `asyncio` internals not affected
by FreezeGun.

We also add more tests that verify how FreezeGun interacts with asyncio
code, including tests that cover the scenario described in spulec#437 which we
aim to fix.

Closes spulec#401
Closes spulec#437
marcinsulikowski added a commit to marcinsulikowski/freezegun that referenced this pull request Feb 20, 2023
The following code:

    async def test():
        with freeze_time("2020-01-01"):
            await asyncio.sleep(0.01)

hangs forever since FreezeGun 1.1.0 because 1.1.0 started patching
`time.monotonic()` (see spulec#369) which is used internally by `asyncio`
event loops to schedule code for execution in the future. This breaks
many projects that uses FreezeGun to test asynchronous code.

We fix this by changing `freeze_time` to patch asyncio event loop's
`time()` method in a way that it uses real monotonic time instead of the
frozen one. Note that we couldn't achieve this by adding `asyncio` to
`DEFAULT_IGNORE_LIST` in `freezegun/config.py` because any running async
code has functions from the `asyncio` module on its stack -- adding
`asyncio` to the ignore list would just disable freezing time in any
async code. This is why we patch one method of a specific class instead.

This change not only fixes `asyncio.sleep()` but also things like
`asyncio.get_running_loop().call_later` (for scheduling task execution
in the future) which in turn makes things like timeouts work in async
code while time is frozen. This may not be desired because some users
may expect that execution of events scheduled to happen in the future
can be controlled using FreezeGun. However, it's not easy to distinguish
between things that users would like to see frozen time and those which
should not (like `asyncio.sleep()`) because all of them use the same
clock. Therefore, we opt for making all `asyncio` internals not affected
by FreezeGun.

We also add more tests that verify how FreezeGun interacts with asyncio
code, including tests that cover the scenario described in spulec#437 which we
aim to fix.

Closes spulec#401
Closes spulec#437
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants