From d64efb6cb1fcce1908d8f0cb37a4940a8bef7b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Mon, 6 May 2024 09:53:32 +0200 Subject: [PATCH] chore: pre-commit --- .github/workflows/tests.yaml | 6 ++ .pre-commit-config.yaml | 19 ++++ LICENSE | 1 - benchmark.py | 11 +-- conftest.py | 2 + libfaketime/__init__.py | 166 ++++++++++++++++++----------------- libfaketime/_version.py | 2 +- pyproject.toml | 13 +++ requirements.txt | 8 +- setup.cfg | 5 ++ setup.py | 89 ++++++++++--------- test/__init__.py | 1 - test/test_faketime.py | 49 ++++++----- test/test_freezegun.py | 25 +++--- test/test_tz.py | 25 ++++-- 15 files changed, 248 insertions(+), 174 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 pyproject.toml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index cc06a01..f2ae33d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -41,3 +41,9 @@ jobs: - run: make -C libfaketime/vendor/libfaketime if: runner.os == 'macOS' - run: tox -e ${{ matrix.python }}-${{ matrix.tz }} --recreate + + style: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d57f3aa --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,19 @@ +--- +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: 'v0.4.3' + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: fix-byte-order-marker + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-toml + - repo: https://github.com/PyCQA/docformatter + rev: v1.7.5 + hooks: + - id: docformatter diff --git a/LICENSE b/LICENSE index d6a9326..d7f1051 100644 --- a/LICENSE +++ b/LICENSE @@ -337,4 +337,3 @@ proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. - diff --git a/benchmark.py b/benchmark.py index 8c3fc0e..ec29211 100644 --- a/benchmark.py +++ b/benchmark.py @@ -2,9 +2,10 @@ import sys import time +from freezegun import freeze_time as freezegun_fake_time + from libfaketime import fake_time as lft_fake_time from libfaketime import reexec_if_needed -from freezegun import freeze_time as freezegun_fake_time def sample(faker): @@ -17,9 +18,9 @@ def sample(faker): return time.perf_counter() - start -if __name__ == '__main__': - if len(sys.argv) > 1 and sys.argv[1] == 'freezegun': +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "freezegun": faker = freezegun_fake_time else: faker = lft_fake_time @@ -27,10 +28,10 @@ def sample(faker): iterations = 1000 - print("timing %s executions of %s" % (iterations, faker)) + print(f"timing {iterations} executions of {faker}") sum = 0 for _ in range(iterations): sum += sample(faker) - print(sum, 'seconds') + print(sum, "seconds") diff --git a/conftest.py b/conftest.py index 6f0d668..1e350ec 100644 --- a/conftest.py +++ b/conftest.py @@ -1,6 +1,8 @@ import os + import libfaketime + def pytest_configure(): libfaketime.reexec_if_needed() _, env_additions = libfaketime.get_reload_information() diff --git a/libfaketime/__init__.py b/libfaketime/__init__.py index 065206b..0763be9 100644 --- a/libfaketime/__init__.py +++ b/libfaketime/__init__.py @@ -1,8 +1,4 @@ -from __future__ import print_function - -from copy import deepcopy import datetime -import dateutil.parser import functools import inspect import os @@ -11,29 +7,26 @@ import time import unittest import uuid +from copy import deepcopy -from pytz import utc, timezone - -try: - basestring -except NameError: - basestring = (str, bytes) - - +import dateutil.parser +from pytz import timezone +from pytz import utc -# When using reexec_if_needed, remove_vars=True and a test loader that purges sys.modules -# (like nose), it can be tough to run reexec_if_needed only once. +# When using reexec_if_needed, remove_vars=True and a test loader that purges +# sys.modules (like nose), it can be tough to run reexec_if_needed only once. # This env var is set by reexec to ensure we don't reload more than once. -_DID_REEXEC_VAR = 'FAKETIME_DID_REEXEC' -_FAKETIME_FMT = '%Y-%m-%d %T.%f' +_DID_REEXEC_VAR = "FAKETIME_DID_REEXEC" +_FAKETIME_FMT = "%Y-%m-%d %T.%f" + def _get_lib_path(): - vendor_dir = 'libfaketime' + vendor_dir = "libfaketime" return os.path.join( - os.path.dirname(__file__), - os.path.join('vendor', vendor_dir, 'src')) + os.path.dirname(__file__), os.path.join("vendor", vendor_dir, "src") + ) def _get_shared_lib(basename): @@ -41,8 +34,8 @@ def _get_shared_lib(basename): def _setup_ld_preload(soname): - if 'LD_PRELOAD' in os.environ: - preload = '{}:{}'.format(soname, os.environ['LD_PRELOAD']) + if "LD_PRELOAD" in os.environ: + preload = "{}:{}".format(soname, os.environ["LD_PRELOAD"]) else: preload = soname @@ -51,24 +44,24 @@ def _setup_ld_preload(soname): # keys are the first 5 chars since we don't care about the version. _lib_addition = { - 'linux': { - 'LD_LIBRARY_PATH': _get_lib_path(), - 'LD_PRELOAD': _setup_ld_preload('libfaketime.so.1') + "linux": { + "LD_LIBRARY_PATH": _get_lib_path(), + "LD_PRELOAD": _setup_ld_preload("libfaketime.so.1"), }, - 'darwi': { - 'DYLD_INSERT_LIBRARIES': _get_shared_lib('libfaketime.1.dylib'), + "darwi": { + "DYLD_INSERT_LIBRARIES": _get_shared_lib("libfaketime.1.dylib"), }, } _other_additions = { - 'linux': { - 'DONT_FAKE_MONOTONIC': '1', - 'FAKETIME_NO_CACHE': '1', + "linux": { + "DONT_FAKE_MONOTONIC": "1", + "FAKETIME_NO_CACHE": "1", }, - 'darwi': { - 'DONT_FAKE_MONOTONIC': '1', - 'DYLD_FORCE_FLAT_NAMESPACE': '1', - 'FAKETIME_NO_CACHE': '1', + "darwi": { + "DONT_FAKE_MONOTONIC": "1", + "DYLD_FORCE_FLAT_NAMESPACE": "1", + "FAKETIME_NO_CACHE": "1", }, } @@ -82,9 +75,9 @@ def get_reload_information(): try: env_additions = _env_additions[sys.platform[:5]] except KeyError: - raise RuntimeError("libfaketime does not support platform %s" % sys.platform) + raise RuntimeError(f"libfaketime does not support platform {sys.platform}") - needs_reload = os.environ.get(_DID_REEXEC_VAR) != 'true' + needs_reload = os.environ.get(_DID_REEXEC_VAR) != "true" return needs_reload, env_additions @@ -94,8 +87,8 @@ def main(): # pragma: nocover _, _env_additions = get_reload_information() for key, value in _env_additions.items(): - print('export %s="%s"' % (key, value)) - print('export %s=true' % _DID_REEXEC_VAR) + print(f'export {key}="{value}"') + print(f"export {_DID_REEXEC_VAR}=true") def reexec_if_needed(remove_vars=True, quiet=False): @@ -103,10 +96,10 @@ def reexec_if_needed(remove_vars=True, quiet=False): if needs_reload: new_environ = os.environ.copy() new_environ.update(env_additions) - new_environ[_DID_REEXEC_VAR] = 'true' + new_environ[_DID_REEXEC_VAR] = "true" args = [sys.executable, [sys.executable] + sys.argv, new_environ] if not quiet: - print('re-exec with libfaketime dependencies') + print("re-exec with libfaketime dependencies") os.execve(*args) if remove_vars: @@ -126,35 +119,50 @@ def end_callback(instance): class fake_time: - def __init__(self, datetime_spec=None, only_main_thread=True, tz_offset=None, timestamp_file=None): + def __init__( + self, + datetime_spec=None, + only_main_thread=True, + tz_offset=None, + timestamp_file=None, + ): self.only_main_thread = only_main_thread - self.timezone_str = 'UTC' + self.timezone_str = "UTC" if tz_offset is not None: - self.timezone_str = 'Etc/GMT{0:+}'.format(-tz_offset) + self.timezone_str = f"Etc/GMT{-tz_offset:+}" if not datetime_spec and not timestamp_file: - raise ValueError("Either 'datetime_spec' or 'timestamp_file' must be passed.") + raise ValueError( + "Either 'datetime_spec' or 'timestamp_file' must be passed." + ) self.time_to_freeze = datetime_spec self.timestamp_file = timestamp_file - if isinstance(datetime_spec, basestring): - self.time_to_freeze = utc.localize(dateutil.parser.parse(datetime_spec)) \ - .astimezone(timezone(self.timezone_str)) + if isinstance(datetime_spec, str): + self.time_to_freeze = utc.localize( + dateutil.parser.parse(datetime_spec) + ).astimezone(timezone(self.timezone_str)) elif isinstance(datetime_spec, datetime.datetime): if datetime_spec.tzinfo: if tz_offset is not None: - raise Exception('Cannot set tz_offset when datetime already has timezone') + raise Exception( + "Cannot set tz_offset when datetime already has timezone" + ) self.timezone_str = datetime_spec.tzinfo.tzname(datetime_spec) def _should_fake(self): - return not self.only_main_thread or threading.current_thread().name == 'MainThread' + return ( + not self.only_main_thread or threading.current_thread().name == "MainThread" + ) _uuid_func_names = ( # < 3.7 - '_uuid_generate_time', + "_uuid_generate_time", # 3.7+ - '_generate_time_safe', '_generate_time') + "_generate_time_safe", + "_generate_time", + ) def _should_patch_uuid(self): # Return the name of the uuid time generate function, or None if not present. @@ -171,12 +179,12 @@ def _format_datetime(self, _datetime): def _update_time(self, time): if not self.timestamp_file: - os.environ['FAKETIME'] = self._format_datetime(time) + os.environ["FAKETIME"] = self._format_datetime(time) else: if time: with open(self.timestamp_file, "w") as fd: fd.write(self._format_datetime(time)) - os.environ['FAKETIME_TIMESTAMP_FILE'] = self.timestamp_file + os.environ["FAKETIME_TIMESTAMP_FILE"] = self.timestamp_file def tick(self, delta=datetime.timedelta(seconds=1)): self.time_to_freeze += delta @@ -185,16 +193,16 @@ def tick(self, delta=datetime.timedelta(seconds=1)): def __enter__(self): if self._should_fake(): begin_callback(self) - self._prev_spec = os.environ.get('FAKETIME') - self._prev_tz = os.environ.get('TZ') - self._prev_fmt = os.environ.get('FAKETIME_FMT') - self._prev_timestamp_file = os.environ.get('FAKETIME_TIMESTAMP_FILE') + self._prev_spec = os.environ.get("FAKETIME") + self._prev_tz = os.environ.get("TZ") + self._prev_fmt = os.environ.get("FAKETIME_FMT") + self._prev_timestamp_file = os.environ.get("FAKETIME_TIMESTAMP_FILE") - os.environ['TZ'] = self.timezone_str + os.environ["TZ"] = self.timezone_str time.tzset() self._update_time(self.time_to_freeze) - os.environ['FAKETIME_FMT'] = _FAKETIME_FMT + os.environ["FAKETIME_FMT"] = _FAKETIME_FMT func_name = self._should_patch_uuid() if func_name: @@ -210,27 +218,27 @@ def __exit__(self, *exc): if self._should_fake(): if self._prev_tz is not None: - os.environ['TZ'] = self._prev_tz + os.environ["TZ"] = self._prev_tz else: - del os.environ['TZ'] + del os.environ["TZ"] time.tzset() if self.timestamp_file: if self._prev_timestamp_file is not None: - os.environ['FAKETIME_TIMESTAMP_FILE'] = self._prev_timestamp_file - elif 'FAKETIME_TIMESTAMP_FILE' in os.environ: - del os.environ['FAKETIME_TIMESTAMP_FILE'] + os.environ["FAKETIME_TIMESTAMP_FILE"] = self._prev_timestamp_file + elif "FAKETIME_TIMESTAMP_FILE" in os.environ: + del os.environ["FAKETIME_TIMESTAMP_FILE"] else: if self._prev_spec is not None: - os.environ['FAKETIME'] = self._prev_spec + os.environ["FAKETIME"] = self._prev_spec else: - del os.environ['FAKETIME'] + del os.environ["FAKETIME"] if self._prev_fmt is not None: - os.environ['FAKETIME_FMT'] = self._prev_spec + os.environ["FAKETIME_FMT"] = self._prev_spec else: - del os.environ['FAKETIME_FMT'] + del os.environ["FAKETIME_FMT"] end_callback(self) @@ -253,9 +261,8 @@ def decorate_class(self, klass): # If it's a TestCase, we assume you want to freeze the time for the # tests, from setUpClass to tearDownClass - # Use getattr as in Python 2.6 they are optional - orig_setUpClass = getattr(klass, 'setUpClass', None) - orig_tearDownClass = getattr(klass, 'tearDownClass', None) + orig_setUpClass = getattr(klass, "setUpClass", None) + orig_tearDownClass = getattr(klass, "tearDownClass", None) @classmethod def setUpClass(cls): @@ -273,13 +280,16 @@ def tearDownClass(cls): klass.tearDownClass = tearDownClass else: - seen = set() - klasses = klass.mro() if hasattr(klass, 'mro') else [klass] + list(klass.__bases__) + klasses = ( + klass.mro() + if hasattr(klass, "mro") + else [klass] + list(klass.__bases__) + ) for base_klass in klasses: - for (attr, attr_value) in base_klass.__dict__.items(): - if attr.startswith('_') or attr in seen: + for attr, attr_value in base_klass.__dict__.items(): + if attr.startswith("_") or attr in seen: continue seen.add(attr) @@ -289,7 +299,8 @@ def tearDownClass(cls): try: setattr(klass, attr, self(attr_value)) except (AttributeError, TypeError): - # Sometimes we can't set this for built-in types and custom callables + # Sometimes we can't set this for built-in types and + # custom callables continue klass._faked_time = self @@ -300,11 +311,8 @@ def wrapper(*args, **kwargs): with self: result = func(*args, **kwargs) return result - functools.update_wrapper(wrapper, func) - # update_wrapper already sets __wrapped__ in Python 3.2+, this is only - # needed for Python 2.x support - wrapper.__wrapped__ = func + functools.update_wrapper(wrapper, func) return wrapper diff --git a/libfaketime/_version.py b/libfaketime/_version.py index afced14..8c0d5d5 100644 --- a/libfaketime/_version.py +++ b/libfaketime/_version.py @@ -1 +1 @@ -__version__ = '2.0.0' +__version__ = "2.0.0" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..06e2e99 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "UP", # pyupgrade +] + +[tool.ruff.lint.isort] +force-single-line = true + +[too.ruff.format] +docstring-code-format = true diff --git a/requirements.txt b/requirements.txt index 9b9f1fa..ac49ba8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ contextdecorator==0.10.0 -freezegun==0.3.13 -mock==2.0.0 -pytest==8.0.0 +freezegun==1.5.0 +mock==5.1.0 +pytest==8.2.0 python-dateutil==2.9.0post0 pytz==2024.1 -tox==4.14.2 +tox==4.15.0 diff --git a/setup.cfg b/setup.cfg index d064409..e53740f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,3 +9,8 @@ setenv = deps = -rrequirements.txt commands = pytest -vs --showlocals {posargs} + +[testenv:style] +commands = + pip install pre-commit + pre-commit run --all-files diff --git a/setup.py b/setup.py index 6add73e..7bcafb3 100644 --- a/setup.py +++ b/setup.py @@ -2,17 +2,18 @@ import os import re -from setuptools import setup, find_packages -from setuptools.command.install import install import subprocess import sys +from setuptools import find_packages +from setuptools import setup +from setuptools.command.install import install # This hack is from http://stackoverflow.com/a/7071358/1231454; # the version is kept in a seperate file and gets parsed - this # way, setup.py doesn't have to import the package. -VERSIONFILE = 'libfaketime/_version.py' +VERSIONFILE = "libfaketime/_version.py" version_line = open(VERSIONFILE).read() version_re = r"^__version__ = ['\"]([^'\"]*)['\"]" @@ -20,28 +21,36 @@ if match: version = match.group(1) else: - raise RuntimeError("Could not find version in '%s'" % VERSIONFILE) + raise RuntimeError(f"Could not find version in '{VERSIONFILE}'") -_vendor_path = 'libfaketime/vendor/libfaketime' +_vendor_path = "libfaketime/vendor/libfaketime" if sys.platform == "linux" or sys.platform == "linux2": - libname = 'libfaketime.so.1' + libname = "libfaketime.so.1" elif sys.platform == "darwin": - libname = 'libfaketime.1.dylib' + libname = "libfaketime.1.dylib" else: - raise RuntimeError("libfaketime does not support platform %s" % sys.platform) + raise RuntimeError("libfaketime does not support platform {sys.platform}") -faketime_lib = os.path.join(_vendor_path, 'src', libname) +faketime_lib = os.path.join(_vendor_path, "src", libname) class CustomInstall(install): def run(self): self.my_outputs = [] if sys.platform in ("linux", "linux2"): - subprocess.check_call(['env', 'FAKETIME_COMPILE_CFLAGS=-UFAKE_STAT -UFAKE_UTIME -UFAKE_SLEEP', 'make', '-C', _vendor_path]) + subprocess.check_call( + [ + "env", + "FAKETIME_COMPILE_CFLAGS=-UFAKE_STAT -UFAKE_UTIME -UFAKE_SLEEP", + "make", + "-C", + _vendor_path, + ] + ) elif sys.platform == "darwin": - subprocess.check_call(['make', '-C', _vendor_path]) + subprocess.check_call(["make", "-C", _vendor_path]) dest = os.path.join(self.install_purelib, os.path.dirname(faketime_lib)) try: @@ -49,7 +58,7 @@ def run(self): except OSError as e: if e.errno != 17: raise - print(faketime_lib, '->', dest) + print(faketime_lib, "->", dest) self.copy_file(faketime_lib, dest) self.my_outputs.append(os.path.join(dest, libname)) @@ -60,44 +69,44 @@ def get_outputs(self): outputs.extend(self.my_outputs) return outputs + setup( - name='libfaketime', + name="libfaketime", version=version, - author='Simon Weber', - author_email='simon@simonmweber.com', - url='http://pypi.python.org/pypi/libfaketime/', - packages=find_packages(exclude=['test']), + author="Simon Weber", + author_email="simon@simonmweber.com", + url="http://pypi.python.org/pypi/libfaketime/", + packages=find_packages(exclude=["test"]), scripts=[], - license='GPLv2', - description='A fast alternative to freezegun that wraps libfaketime.', - long_description=(open('README.md').read() + '\n\n' + - open('CHANGELOG.md').read()), - long_description_content_type='text/markdown', + license="GPLv2", + description="A fast alternative to freezegun that wraps libfaketime.", + long_description=(open("README.md").read() + "\n\n" + open("CHANGELOG.md").read()), + long_description_content_type="text/markdown", install_requires=[ - 'python-dateutil >= 1.3, != 2.0', # 2.0 is python3-only - 'pytz', # for pytz.timezone and pytz.utc + "python-dateutil >= 1.3", + "pytz", # for pytz.timezone and pytz.utc ], classifiers=[ - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', - 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Topic :: Software Development :: Libraries :: Python Modules', + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Software Development :: Libraries :: Python Modules", ], include_package_data=True, zip_safe=False, - cmdclass={'install': CustomInstall}, + cmdclass={"install": CustomInstall}, entry_points={ - 'console_scripts': [ - 'python-libfaketime = libfaketime:main', + "console_scripts": [ + "python-libfaketime = libfaketime:main", ] }, ) diff --git a/test/__init__.py b/test/__init__.py index 8b13789..e69de29 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1 +0,0 @@ - diff --git a/test/test_faketime.py b/test/test_faketime.py index ad9fe49..6d56e26 100644 --- a/test/test_faketime.py +++ b/test/test_faketime.py @@ -1,24 +1,25 @@ import datetime -import time import os +import time import uuid +from unittest.mock import patch -from mock import patch import pytest import libfaketime -from libfaketime import fake_time, freeze_time +from libfaketime import fake_time +from libfaketime import freeze_time -class TestReexec(): - @patch('os.execve') - @patch('sys.platform', 'win32') +class TestReexec: + @patch("os.execve") + @patch("sys.platform", "win32") def test_reexec_windows_fails(self, exec_patch): with pytest.raises(RuntimeError): libfaketime.reexec_if_needed() -class TestFaketime(): +class TestFaketime: def _assert_time_not_faked(self): # This just makes sure that non-faked time is dynamic; # I can't think of a good way to check that the non-faked time is "real". @@ -30,7 +31,7 @@ def _assert_time_not_faked(self): assert second > first def test_fake_time_tick(self): - with fake_time('2000-01-01 10:00:05') as fake: + with fake_time("2000-01-01 10:00:05") as fake: assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.now() fake.tick(delta=datetime.timedelta(hours=1)) assert datetime.datetime(2000, 1, 1, 11, 0, 5) == datetime.datetime.now() @@ -45,35 +46,37 @@ def test_fake_time_is_static(self): assert second == first - @fake_time('2000-01-01 10:00:05') + @fake_time("2000-01-01 10:00:05") def test_fake_time_parses_easy_strings(self): assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.now() assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.utcnow() def test_fake_time_parses_easy_strings_with_timezones(self): - with fake_time('2000-01-01 10:00:05', tz_offset=3): + with fake_time("2000-01-01 10:00:05", tz_offset=3): assert datetime.datetime(2000, 1, 1, 13, 0, 5) == datetime.datetime.now() assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.utcnow() - with fake_time('2000-01-01 10:00:05', tz_offset=-3): + with fake_time("2000-01-01 10:00:05", tz_offset=-3): assert datetime.datetime(2000, 1, 1, 7, 0, 5) == datetime.datetime.now() assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.utcnow() - @fake_time('march 1st, 2014 at 1:59pm') + @fake_time("march 1st, 2014 at 1:59pm") def test_fake_time_parses_tough_strings(self): assert datetime.datetime(2014, 3, 1, 13, 59) == datetime.datetime.now() @fake_time(datetime.datetime(2014, 1, 1, microsecond=123456)) def test_fake_time_has_microsecond_granularity(self): - assert datetime.datetime(2014, 1, 1, microsecond=123456) == datetime.datetime.now() + assert ( + datetime.datetime(2014, 1, 1, microsecond=123456) == datetime.datetime.now() + ) def test_nested_fake_time(self): self._assert_time_not_faked() - with fake_time('1/1/2000'): + with fake_time("1/1/2000"): assert datetime.datetime(2000, 1, 1) == datetime.datetime.now() - with fake_time('1/1/2001'): + with fake_time("1/1/2001"): assert datetime.datetime(2001, 1, 1) == datetime.datetime.now() assert datetime.datetime(2000, 1, 1) == datetime.datetime.now() @@ -81,16 +84,16 @@ def test_nested_fake_time(self): self._assert_time_not_faked() def test_freeze_time_alias(self): - with freeze_time('2000-01-01 10:00:05'): + with freeze_time("2000-01-01 10:00:05"): assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.now() def test_monotonic_not_mocked(self): - assert os.environ['DONT_FAKE_MONOTONIC'] == '1' + assert os.environ["DONT_FAKE_MONOTONIC"] == "1" def test_timestmap_file(self, tmpdir): file_path = str(tmpdir / "faketime.rc") - with fake_time('2000-01-01 10:00:05', timestamp_file=file_path) as fake: + with fake_time("2000-01-01 10:00:05", timestamp_file=file_path) as fake: assert datetime.datetime(2000, 1, 1, 10, 0, 5) == datetime.datetime.now() with open(file_path) as fd: assert fd.read() == "2000-01-01 10:00:05.000000" @@ -103,23 +106,23 @@ def test_timestmap_file(self, tmpdir): with fake_time(timestamp_file=file_path): assert datetime.datetime(2000, 1, 1, 11, 0, 5) == datetime.datetime.now() -class TestUUID1Deadlock(): +class TestUUID1Deadlock: @fake_time(datetime.datetime.now()) def test_uuid1_does_not_deadlock(self): - """This test will deadlock if we fail to patch a system level uuid library.""" + """This test will deadlock if we fail to patch a system level uuid + library.""" for i in range(100): uuid.uuid1() -@fake_time('2000-01-01') +@fake_time("2000-01-01") class TestClassDecorator: - def test_simple(self): assert datetime.datetime(2000, 1, 1) == datetime.datetime.now() self._faked_time.tick() assert datetime.datetime(2000, 1, 1, 0, 0, 1) == datetime.datetime.now() - @fake_time('2001-01-01') + @fake_time("2001-01-01") def test_overwrite_with_func_decorator(self): assert datetime.datetime(2001, 1, 1) == datetime.datetime.now() diff --git a/test/test_freezegun.py b/test/test_freezegun.py index 4b46825..3f6c88c 100644 --- a/test/test_freezegun.py +++ b/test/test_freezegun.py @@ -1,36 +1,39 @@ -import pytest -import time import datetime +import time +import pytest from freezegun import freeze_time + from libfaketime import fake_time # TODO # - Fix time.localtime # - Fix time.strftime -# - Fix python2 time.time with 1970-01-01 + +assert time +assert datetime test_functions = [ ("datetime.datetime.now", (), {}), ("datetime.datetime.utcnow", (), {}), ("time.time", (), {}), -# ("time.localtime", (), {}), -# ("time.strftime", ("%Y-%m-%d %H:%M:%S %Z",), {}), - ("datetime.date", (), {"year": 1970, "month":1, "day":1}), - ("datetime.datetime", (), {"year": 1970, "month":1, "day":1}), + # ("time.localtime", (), {}), + # ("time.strftime", ("%Y-%m-%d %H:%M:%S %Z",), {}), + ("datetime.date", (), {"year": 1970, "month": 1, "day": 1}), + ("datetime.datetime", (), {"year": 1970, "month": 1, "day": 1}), ] + @pytest.mark.parametrize("test_function", test_functions) @pytest.mark.parametrize("tz_offset", [0, 12]) -@pytest.mark.parametrize("date_to_freeze", ["1970-01-01 00:00:01"]) +@pytest.mark.parametrize("date_to_freeze", ["1970-01-01 00:00:01"]) def test_compare_against_freezegun_results(test_function, tz_offset, date_to_freeze): func_name, args, kwargs = test_function - with fake_time(date_to_freeze, tz_offset = tz_offset): + with fake_time(date_to_freeze, tz_offset=tz_offset): libfaketime_result = eval(func_name)(*args, **kwargs) - with freeze_time(date_to_freeze, tz_offset = tz_offset): + with freeze_time(date_to_freeze, tz_offset=tz_offset): freezegun_result = eval(func_name)(*args, **kwargs) assert freezegun_result == libfaketime_result - diff --git a/test/test_tz.py b/test/test_tz.py index 3783e08..fd70186 100644 --- a/test/test_tz.py +++ b/test/test_tz.py @@ -1,7 +1,7 @@ import datetime -import dateutil.tz import os +import dateutil.tz import pytest from pytz import timezone @@ -25,8 +25,10 @@ def test_timezone_is_restored_after_context_manager_usage(): def test_tzinfo_is_normalized(): """Ensure utcnow() behaves correctly when faking non-UTC timestamps.""" - timezone_to_test_with = timezone('Europe/Brussels') - time_to_freeze = timezone_to_test_with.localize(datetime.datetime(2017, 1, 2, 15, 2)) + timezone_to_test_with = timezone("Europe/Brussels") + time_to_freeze = timezone_to_test_with.localize( + datetime.datetime(2017, 1, 2, 15, 2) + ) with fake_time(time_to_freeze): # The timeshift of Europe/Brussels is UTC+1 in January @@ -35,15 +37,20 @@ def test_tzinfo_is_normalized(): def test_block_setting_of_conflicting_tz_info(): - """Cannot pass in tz_offset when the timestamp already carries a timezone.""" + """Cannot pass in tz_offset when the timestamp already carries a + timezone.""" with pytest.raises(Exception) as exc_info: - timezone_to_test_with = timezone('America/Havana') - time_to_freeze = timezone_to_test_with.localize(datetime.datetime(2012, 10, 2, 21, 38)) + timezone_to_test_with = timezone("America/Havana") + time_to_freeze = timezone_to_test_with.localize( + datetime.datetime(2012, 10, 2, 21, 38) + ) with fake_time(time_to_freeze, tz_offset=5): pass - assert str(exc_info.value) == 'Cannot set tz_offset when datetime already has timezone' + assert ( + str(exc_info.value) == "Cannot set tz_offset when datetime already has timezone" + ) @pytest.mark.parametrize("offset", range(-2, 3)) @@ -52,13 +59,13 @@ def test_generated_tz_is_valid(offset): now = datetime.datetime.now() with fake_time(now, tz_offset=offset): - fake_tz = os.environ['TZ'] + fake_tz = os.environ["TZ"] timezone(fake_tz) # should not raise pytzdata.exceptions.TimezoneNotFound def test_dateutil_tz_is_valid(): test_dt = datetime.datetime(2017, 1, 2, 15, 2) - dateutil_tzinfo = dateutil.tz.gettz('UTC') + dateutil_tzinfo = dateutil.tz.gettz("UTC") dt_dateutil_tzinfo = test_dt.replace(tzinfo=dateutil_tzinfo) # Should be compatible with a dateutil tzinfo object, not just pytz