A fast alternative to freezegun that wraps libfaketime.
Project description
python-libfaketime is a wrapper of libfaketime for python. Some brief details:
Linux and OS X, Pythons 3.5 through 3.8, pypy and pypy3
Mostly compatible with freezegun.
Microsecond resolution.
Accepts datetimes and strings that can be parsed by dateutil.
Not threadsafe.
Will break profiling. A workaround: use libfaketime.{begin, end}_callback to disable/enable your profiler (nosetest example).
Installation
$ pip install libfaketime
Usage
import datetime
from libfaketime import fake_time, reexec_if_needed
# libfaketime needs to be preloaded by the dynamic linker.
# This will exec the same command, but with the proper environment variables set.
# You can also skip this and manually manage your env (see "How to avoid re-exec").
reexec_if_needed()
def test_datetime_now():
# fake_time can be used as a context_manager
with fake_time('1970-01-01 00:00:01'):
# Every calls to a date or datetime function returns the mocked date
assert datetime.datetime.utcnow() == datetime.datetime(1970, 1, 1, 0, 0, 1)
assert datetime.datetime.now() == datetime.datetime(1970, 1, 1, 0, 0, 1)
assert time.time() == 1
# fake_time can also be used as a decorator
@fake_time('1970-01-01 00:00:01', tz_offset=12)
def test_datetime_now_with_offset():
# datetime.utcnow returns the mocked datetime without offset
assert datetime.datetime.utcnow() == datetime.datetime(1970, 1, 1, 0, 0, 1)
# datetime.now returns the mocked datetime with the offset passed to fake_time
assert datetime.datetime.now() == datetime.datetime(1970, 1, 1, 12, 0, 1)
Performance
libfaketime tends to be significantly faster than freezegun. Here’s the output of a totally unscientific benchmark on my laptop:
$ python benchmark.py
re-exec with libfaketime dependencies
timing 1000 executions of <class 'libfaketime.fake_time'>
0.021755 seconds
$ python benchmark.py freezegun
timing 1000 executions of <function freeze_time at 0x10aaa1140>
6.561472 seconds
Use with py.test
The pytest-libfaketime plugin will automatically configure python-libfaketime for you:
$ pip install pytest-libfaketime
Alternatively, you can reexec manually from inside the pytest_configure hook:
# conftest.py
import os
import libfaketime
def pytest_configure():
libfaketime.reexec_if_needed()
_, env_additions = libfaketime.get_reload_information()
os.environ.update(env_additions)
Use with tox
In your tox configuration file, under the testenv bloc, add the libfaketime environment variables to avoid re-execution:
setenv =
LD_PRELOAD = {envsitepackagesdir}/libfaketime/vendor/libfaketime/src/libfaketime.so.1
DONT_FAKE_MONOTONIC = 1
FAKETIME_DID_REEXEC = true
Migration from freezegun
python-libfaketime should have the same behavior as freezegun when running on supported code. To migrate to it, you can run:
find . -type f -name "*.py" -exec sed -i 's/freezegun/libfaketime/g' "{}" \;
How to avoid re-exec
In some cases - especially when your tests start other processes - re-execing can cause unexpected problems. To avoid this, you can preload the necessary environment variables yourself. The necessary environment for your system can be found by running python-libfaketime on the command line:
$ python-libfaketime
export LD_PRELOAD="/home/foo/<snip>/vendor/libfaketime/src/libfaketime.so.1"
export DONT_FAKE_MONOTONIC="1"
export FAKETIME_DID_REEXEC=true
You can easily put this in a script like:
$ eval $(python-libfaketime)
$ pytest # ...or any other code that imports libfaketime
Contributing and testing
Contributions are welcome! You should compile libfaketime before running tests:
make -C libfaketime/vendor/libfaketime
Then you can install requirements with pip install -r requirements.txt and use pytest and tox to run the tests.
uuid1 deadlock
Calling uuid.uuid1() multiple times while in a fake_time context can result in a deadlock when an OS-level uuid library is available. To avoid this, python-libtaketime will monkeypatch uuid._uuid_generate_time (or similar, it varies by version) to None inside a fake_time context. This may slow down uuid1 generation but should not affect correctness.
Changelog
Semantic versioning is used.
2.0.0
released 2020-04-17
1.2.1
released 2019-01-20
fix a deadlock on python 3.7+
1.2.0
released 2018-10-28
offset-aware datetimes now properly fake the timezone as well: #49
1.1.0
released 2018-10-07
decorated classes can access the fake_time object with self._faked_time: #47
1.0.0
released 2018-06-16
0.5.2
released 2018-05-19
0.5.1
released 2018-01-19
fix usage as a class decorator : #41
0.5.0
released 2017-09-10
0.4.4
released 2017-07-16
allow contextlib2 as an alternative to contextdecorator: #30
0.4.3
released 2017-07-07
add macOS Sierra compatibility: #29
0.4.2
released 2016-06-30
fix only_main_thread=False: #24
0.4.1
released 2016-05-02
0.4.0
released 2016-04-02
freezegun’s tick() is now supported; see their docs for usage.
0.3.0
released 2016-03-04
invoking libfaketime from the command line will now print the necessary environment to avoid a re-exec.
0.2.1
released 2016-03-01
python 3 support
0.1.1
released 2015-09-11
prevent distribution of test directory: https://github.com/simon-weber/python-libfaketime/pull/4
0.1.0
released 2015-06-23
add global start/stop callbacks
0.0.3
released 2015-03-28
initial packaged release
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.