diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 42c20ab1..a235a7d3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,9 +5,14 @@ on: - push jobs: - mypy: - name: mypy + lint: + name: ${{ matrix.tox-target }} runs-on: ubuntu-latest + strategy: + matrix: + tox-target: + - lint + - mypy steps: - uses: actions/checkout@master @@ -19,7 +24,7 @@ jobs: run: pip install tox - name: Run tests - run: tox -e mypy + run: tox -e ${{ matrix.tox-target }} tests: name: Python ${{ matrix.python-version }} diff --git a/create_tag.py b/create_tag.py index 16e2dfa5..58d72f1d 100644 --- a/create_tag.py +++ b/create_tag.py @@ -3,8 +3,8 @@ def read_version(): - with open(os.path.join('freezegun', '__init__.py')) as f: - m = re.search(r'''__version__\s*=\s*['"]([^'"]*)['"]''', f.read()) + with open(os.path.join("freezegun", "__init__.py")) as f: + m = re.search(r"""__version__\s*=\s*['"]([^'"]*)['"]""", f.read()) if m: return m.group(1) raise ValueError("couldn't find version") @@ -12,11 +12,14 @@ def read_version(): def create_tag(): from subprocess import call + version = read_version() - errno = call(['git', 'tag', '--annotate', version, '--message', 'Version %s' % version]) + errno = call( + ["git", "tag", "--annotate", version, "--message", "Version %s" % version] + ) if errno == 0: print("Added tag for version %s" % version) -if __name__ == '__main__': +if __name__ == "__main__": create_tag() diff --git a/freezegun/__init__.py b/freezegun/__init__.py index 9be5298c..d9d9489f 100644 --- a/freezegun/__init__.py +++ b/freezegun/__init__.py @@ -8,11 +8,11 @@ from .api import freeze_time from .config import configure -__title__ = 'freezegun' -__version__ = '1.1.0' -__author__ = 'Steve Pulec' -__license__ = 'Apache License 2.0' -__copyright__ = 'Copyright 2012 Steve Pulec' +__title__ = "freezegun" +__version__ = "1.1.0" +__author__ = "Steve Pulec" +__license__ = "Apache License 2.0" +__copyright__ = "Copyright 2012 Steve Pulec" __all__ = ["freeze_time", "configure"] diff --git a/freezegun/__init__.pyi b/freezegun/__init__.pyi index 17dd86ac..1de0916f 100644 --- a/freezegun/__init__.pyi +++ b/freezegun/__init__.pyi @@ -1,2 +1 @@ from .api import freeze_time as freeze_time - diff --git a/freezegun/_async.py b/freezegun/_async.py index 63045d89..60c76ce2 100644 --- a/freezegun/_async.py +++ b/freezegun/_async.py @@ -1,7 +1,6 @@ import functools from typing import Any, Callable, TypeVar, cast - _CallableT = TypeVar("_CallableT", bound=Callable[..., Any]) diff --git a/freezegun/api.py b/freezegun/api.py index 81d4da17..3bbc3dde 100644 --- a/freezegun/api.py +++ b/freezegun/api.py @@ -1,31 +1,32 @@ -from . import config -from ._async import wrap_coroutine +import calendar import copyreg -import dateutil import datetime import functools +import inspect +import numbers +import platform import sys import time -import uuid -import calendar +import types import unittest -import platform +import uuid import warnings -import types -import numbers -import inspect +import dateutil from dateutil import parser from dateutil.tz import tzlocal +from . import config +from ._async import wrap_coroutine + try: from maya import MayaDT except ImportError: MayaDT = None -_TIME_NS_PRESENT = hasattr(time, 'time_ns') -_MONOTONIC_NS_PRESENT = hasattr(time, 'monotonic_ns') -_PERF_COUNTER_NS_PRESENT = hasattr(time, 'perf_counter_ns') +_TIME_NS_PRESENT = hasattr(time, "time_ns") +_MONOTONIC_NS_PRESENT = hasattr(time, "monotonic_ns") +_PERF_COUNTER_NS_PRESENT = hasattr(time, "perf_counter_ns") _EPOCH = datetime.datetime(1970, 1, 1) _EPOCHTZ = datetime.datetime(1970, 1, 1, tzinfo=dateutil.tz.UTC) @@ -37,7 +38,16 @@ real_strftime = time.strftime real_date = datetime.date real_datetime = datetime.datetime -real_date_objects = [real_time, real_localtime, real_gmtime, real_monotonic, real_perf_counter, real_strftime, real_date, real_datetime] +real_date_objects = [ + real_time, + real_localtime, + real_gmtime, + real_monotonic, + real_perf_counter, + real_strftime, + real_date, + real_datetime, +] if _TIME_NS_PRESENT: real_time_ns = time.time_ns @@ -54,7 +64,7 @@ _real_time_object_ids = {id(obj) for obj in real_date_objects} # time.clock is deprecated and was removed in Python 3.8 -real_clock = getattr(time, 'clock', None) +real_clock = getattr(time, "clock", None) freeze_factories = [] tz_offsets = [] @@ -64,13 +74,13 @@ try: # noinspection PyUnresolvedReferences real_uuid_generate_time = uuid._uuid_generate_time - uuid_generate_time_attr = '_uuid_generate_time' + uuid_generate_time_attr = "_uuid_generate_time" except AttributeError: # noinspection PyUnresolvedReferences uuid._load_system_functions() # noinspection PyUnresolvedReferences real_uuid_generate_time = uuid._generate_time_safe - uuid_generate_time_attr = '_generate_time_safe' + uuid_generate_time_attr = "_generate_time_safe" except ImportError: real_uuid_generate_time = None uuid_generate_time_attr = None @@ -82,7 +92,8 @@ real_uuid_create = None -# keep a cache of module attributes otherwise freezegun will need to analyze too many modules all the time +# Keep a cache of module attributes otherwise freezegun will need to analyze +# too many modules all the time. _GLOBAL_MODULES_CACHE = {} @@ -96,7 +107,8 @@ def _get_module_attributes(module): try: attribute_value = getattr(module, attribute_name) except (ImportError, AttributeError, TypeError): - # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery) + # For certain libraries, this can result in ImportError(_winreg) or + # AttributeError (celery). continue else: result.append((attribute_name, attribute_value)) @@ -109,7 +121,10 @@ def _setup_module_cache(module): for attribute_name, attribute_value in all_module_attributes: if id(attribute_value) in _real_time_object_ids: date_attrs.append((attribute_name, attribute_value)) - _GLOBAL_MODULES_CACHE[module.__name__] = (_get_module_attributes_hash(module), date_attrs) + _GLOBAL_MODULES_CACHE[module.__name__] = ( + _get_module_attributes_hash(module), + date_attrs, + ) def _get_module_attributes_hash(module): @@ -117,11 +132,11 @@ def _get_module_attributes_hash(module): module_dir = dir(module) except (ImportError, TypeError): module_dir = [] - return f'{id(module)}-{hash(frozenset(module_dir))}' + return f"{id(module)}-{hash(frozenset(module_dir))}" def _get_cached_module_attributes(module): - module_hash, cached_attrs = _GLOBAL_MODULES_CACHE.get(module.__name__, ('0', [])) + module_hash, cached_attrs = _GLOBAL_MODULES_CACHE.get(module.__name__, ("0", [])) if _get_module_attributes_hash(module) == module_hash: return cached_attrs @@ -133,8 +148,8 @@ def _get_cached_module_attributes(module): _is_cpython = ( - hasattr(platform, 'python_implementation') and - platform.python_implementation().lower() == "cpython" + hasattr(platform, "python_implementation") + and platform.python_implementation().lower() == "cpython" ) @@ -155,7 +170,7 @@ def _should_use_real_time(): frame = inspect.currentframe().f_back.f_back for _ in range(call_stack_inspection_limit): - module_name = frame.f_globals.get('__name__') + module_name = frame.f_globals.get("__name__") if module_name and module_name.startswith(ignore_lists[-1]): return True @@ -174,9 +189,13 @@ def fake_time(): if _should_use_real_time(): return real_time() current_time = get_current_time() - return calendar.timegm(current_time.timetuple()) + current_time.microsecond / 1000000.0 + return ( + calendar.timegm(current_time.timetuple()) + current_time.microsecond / 1000000.0 + ) + if _TIME_NS_PRESENT: + def fake_time_ns(): if _should_use_real_time(): return real_time_ns() @@ -203,18 +222,14 @@ def fake_gmtime(t=None): def _get_fake_monotonic(): # For monotonic timers like .monotonic(), .perf_counter(), etc current_time = get_current_time() - return ( - calendar.timegm(current_time.timetuple()) + - current_time.microsecond / 1e6 - ) + return calendar.timegm(current_time.timetuple()) + current_time.microsecond / 1e6 def _get_fake_monotonic_ns(): # For monotonic timers like .monotonic(), .perf_counter(), etc current_time = get_current_time() return ( - calendar.timegm(current_time.timetuple()) * 1000000 + - current_time.microsecond + calendar.timegm(current_time.timetuple()) * 1000000 + current_time.microsecond ) * 1000 @@ -233,6 +248,7 @@ def fake_perf_counter(): if _MONOTONIC_NS_PRESENT: + def fake_monotonic_ns(): if _should_use_real_time(): return real_monotonic_ns() @@ -241,6 +257,7 @@ def fake_monotonic_ns(): if _PERF_COUNTER_NS_PRESENT: + def fake_perf_counter_ns(): if _should_use_real_time(): return real_perf_counter_ns() @@ -257,7 +274,9 @@ def fake_strftime(format, time_to_format=None): else: return real_strftime(format, time_to_format) + if real_clock is not None: + def fake_clock(): if _should_use_real_time(): return real_clock() @@ -268,7 +287,7 @@ def fake_clock(): first_frozen_time = freeze_factories[0]() last_frozen_time = get_current_time() - timedelta = (last_frozen_time - first_frozen_time) + timedelta = last_frozen_time - first_frozen_time total_seconds = timedelta.total_seconds() if tick_flags[-1]: @@ -288,20 +307,20 @@ def __subclasscheck__(cls, subclass): def datetime_to_fakedatetime(datetime): - return FakeDatetime(datetime.year, - datetime.month, - datetime.day, - datetime.hour, - datetime.minute, - datetime.second, - datetime.microsecond, - datetime.tzinfo) + return FakeDatetime( + datetime.year, + datetime.month, + datetime.day, + datetime.hour, + datetime.minute, + datetime.second, + datetime.microsecond, + datetime.tzinfo, + ) def date_to_fakedate(date): - return FakeDate(date.year, - date.month, - date.day) + return FakeDate(date.year, date.month, date.day) class FakeDate(real_date, metaclass=FakeDateMeta): @@ -333,6 +352,7 @@ def _date_to_freeze(): def _tz_offset(cls): return tz_offsets[-1] + FakeDate.min = date_to_fakedate(real_date.min) FakeDate.max = date_to_fakedate(real_date.max) @@ -372,8 +392,8 @@ def astimezone(self, tz=None): def fromtimestamp(cls, t, tz=None): if tz is None: return real_datetime.fromtimestamp( - t, tz=dateutil.tz.tzoffset("freezegun", cls._tz_offset()) - ).replace(tzinfo=None) + t, tz=dateutil.tz.tzoffset("freezegun", cls._tz_offset()) + ).replace(tzinfo=None) return datetime_to_fakedatetime(real_datetime.fromtimestamp(t, tz)) def timestamp(self): @@ -484,7 +504,6 @@ def _parse_tz_offset(tz_offset): class TickingDateTimeFactory: - def __init__(self, time_to_freeze, start): self.time_to_freeze = time_to_freeze self.start = start @@ -494,7 +513,6 @@ def __call__(self): class FrozenDateTimeFactory: - def __init__(self, time_to_freeze): self.time_to_freeze = time_to_freeze @@ -516,7 +534,6 @@ def move_to(self, target_datetime): class StepTickTimeFactory: - def __init__(self, time_to_freeze, step_width): self.time_to_freeze = time_to_freeze self.step_width = step_width @@ -542,8 +559,16 @@ def move_to(self, target_datetime): class _freeze_time: - - def __init__(self, time_to_freeze_str, tz_offset, ignore, tick, as_arg, as_kwarg, auto_tick_seconds): + def __init__( + self, + time_to_freeze_str, + tz_offset, + ignore, + tick, + as_arg, + as_kwarg, + auto_tick_seconds, + ): self.time_to_freeze = _parse_time_to_freeze(time_to_freeze_str) self.tz_offset = _parse_tz_offset(tz_offset) self.ignore = tuple(ignore) @@ -595,7 +620,7 @@ def tearDownClass(cls): klasses = klass.mro() for base_klass in klasses: for (attr, attr_value) in base_klass.__dict__.items(): - if attr.startswith('_') or attr in seen: + if attr.startswith("_") or attr in seen: continue seen.add(attr) @@ -605,7 +630,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 return klass @@ -618,9 +644,13 @@ def __exit__(self, *args): def start(self): if self.auto_tick_seconds: - freeze_factory = StepTickTimeFactory(self.time_to_freeze, self.auto_tick_seconds) + freeze_factory = StepTickTimeFactory( + self.time_to_freeze, self.auto_tick_seconds + ) elif self.tick: - freeze_factory = TickingDateTimeFactory(self.time_to_freeze, real_datetime.now()) + freeze_factory = TickingDateTimeFactory( + self.time_to_freeze, real_datetime.now() + ) else: freeze_factory = FrozenDateTimeFactory(self.time_to_freeze) @@ -653,32 +683,34 @@ def start(self): # Change any place where the module had already been imported to_patch = [ - ('real_date', real_date, FakeDate), - ('real_datetime', real_datetime, FakeDatetime), - ('real_gmtime', real_gmtime, fake_gmtime), - ('real_localtime', real_localtime, fake_localtime), - ('real_monotonic', real_monotonic, fake_monotonic), - ('real_perf_counter', real_perf_counter, fake_perf_counter), - ('real_strftime', real_strftime, fake_strftime), - ('real_time', real_time, fake_time), + ("real_date", real_date, FakeDate), + ("real_datetime", real_datetime, FakeDatetime), + ("real_gmtime", real_gmtime, fake_gmtime), + ("real_localtime", real_localtime, fake_localtime), + ("real_monotonic", real_monotonic, fake_monotonic), + ("real_perf_counter", real_perf_counter, fake_perf_counter), + ("real_strftime", real_strftime, fake_strftime), + ("real_time", real_time, fake_time), ] if _TIME_NS_PRESENT: time.time_ns = fake_time_ns - to_patch.append(('real_time_ns', real_time_ns, fake_time_ns)) + to_patch.append(("real_time_ns", real_time_ns, fake_time_ns)) if _MONOTONIC_NS_PRESENT: time.monotonic_ns = fake_monotonic_ns - to_patch.append(('real_monotonic_ns', real_monotonic_ns, fake_monotonic_ns)) + to_patch.append(("real_monotonic_ns", real_monotonic_ns, fake_monotonic_ns)) if _PERF_COUNTER_NS_PRESENT: time.perf_counter_ns = fake_perf_counter_ns - to_patch.append(('real_perf_counter_ns', real_perf_counter_ns, fake_perf_counter_ns)) + to_patch.append( + ("real_perf_counter_ns", real_perf_counter_ns, fake_perf_counter_ns) + ) if real_clock is not None: # time.clock is deprecated and was removed in Python 3.8 time.clock = fake_clock - to_patch.append(('real_clock', real_clock, fake_clock)) + to_patch.append(("real_clock", real_clock, fake_clock)) self.fake_names = tuple(fake.__name__ for real_name, real, fake in to_patch) self.reals = {id(fake): real for real_name, real, fake in to_patch} @@ -689,14 +721,19 @@ def start(self): self.modules_at_start = set(sys.modules.keys()) with warnings.catch_warnings(): - warnings.filterwarnings('ignore') + warnings.filterwarnings("ignore") for mod_name, module in list(sys.modules.items()): if mod_name is None or module is None or mod_name == __name__: continue - elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'): + elif mod_name.startswith(self.ignore) or mod_name.endswith( + ".six.moves" + ): continue - elif (not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time')): + elif not hasattr(module, "__name__") or module.__name__ in ( + "datetime", + "time", + ): continue module_attrs = _get_cached_module_attributes(module) @@ -727,14 +764,19 @@ def stop(self): modules_to_restore = set(sys.modules.keys()) - self.modules_at_start self.modules_at_start = set() with warnings.catch_warnings(): - warnings.simplefilter('ignore') + warnings.simplefilter("ignore") for mod_name in modules_to_restore: module = sys.modules.get(mod_name, None) if mod_name is None or module is None: continue - elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'): + elif mod_name.startswith(self.ignore) or mod_name.endswith( + ".six.moves" + ): continue - elif not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time'): + elif not hasattr(module, "__name__") or module.__name__ in ( + "datetime", + "time", + ): continue for module_attribute in dir(module): @@ -743,7 +785,8 @@ def stop(self): try: attribute_value = getattr(module, module_attribute) except (ImportError, AttributeError, TypeError): - # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery) + # For certain libraries, this can result in + # ImportError(_winreg) or AttributeError (celery). continue real = self.reals.get(id(attribute_value)) @@ -779,7 +822,10 @@ def decorate_callable(self, func): def wrapper(*args, **kwargs): with self as time_factory: if self.as_arg and self.as_kwarg: - assert False, "You can't specify both as_arg and as_kwarg at the same time. Pick one." + assert False, ( + "You can't specify both as_arg and as_kwarg at the same time. " + "Pick one." + ) elif self.as_arg: result = func(time_factory, *args, **kwargs) elif self.as_kwarg: @@ -788,35 +834,56 @@ def wrapper(*args, **kwargs): else: result = func(*args, **kwargs) return result + functools.update_wrapper(wrapper, func) return wrapper -def freeze_time(time_to_freeze=None, tz_offset=0, ignore=None, tick=False, as_arg=False, as_kwarg='', - auto_tick_seconds=0): - acceptable_times = (type(None), str, datetime.date, datetime.timedelta, - types.FunctionType, types.GeneratorType) +def freeze_time( + time_to_freeze=None, + tz_offset=0, + ignore=None, + tick=False, + as_arg=False, + as_kwarg="", + auto_tick_seconds=0, +): + acceptable_times = ( + type(None), + str, + datetime.date, + datetime.timedelta, + types.FunctionType, + types.GeneratorType, + ) if MayaDT is not None: - acceptable_times += MayaDT, + acceptable_times += (MayaDT,) if not isinstance(time_to_freeze, acceptable_times): - raise TypeError(('freeze_time() expected None, a string, date instance, datetime ' - 'instance, MayaDT, timedelta instance, function or a generator, but got ' - 'type {}.').format(type(time_to_freeze))) + raise TypeError( + ( + "freeze_time() expected None, a string, date instance, datetime " + "instance, MayaDT, timedelta instance, function or a generator, but " + "got type {}." + ).format(type(time_to_freeze)) + ) if tick and not _is_cpython: - raise SystemError('Calling freeze_time with tick=True is only compatible with CPython') + raise SystemError( + "Calling freeze_time with tick=True is only compatible with CPython" + ) if isinstance(time_to_freeze, types.FunctionType): return freeze_time(time_to_freeze(), tz_offset, ignore, tick, auto_tick_seconds) if isinstance(time_to_freeze, types.GeneratorType): - return freeze_time(next(time_to_freeze), tz_offset, ignore, tick, auto_tick_seconds) + return freeze_time( + next(time_to_freeze), tz_offset, ignore, tick, auto_tick_seconds + ) if MayaDT is not None and isinstance(time_to_freeze, MayaDT): - return freeze_time(time_to_freeze.datetime(), tz_offset, ignore, - tick, as_arg) + return freeze_time(time_to_freeze.datetime(), tz_offset, ignore, tick, as_arg) if ignore is None: ignore = [] @@ -862,5 +929,9 @@ def adapt_datetime(val): else: pymysql.converters.encoders[FakeDate] = pymysql.converters.encoders[real_date] pymysql.converters.conversions[FakeDate] = pymysql.converters.encoders[real_date] - pymysql.converters.encoders[FakeDatetime] = pymysql.converters.encoders[real_datetime] - pymysql.converters.conversions[FakeDatetime] = pymysql.converters.encoders[real_datetime] + pymysql.converters.encoders[FakeDatetime] = pymysql.converters.encoders[ + real_datetime + ] + pymysql.converters.conversions[FakeDatetime] = pymysql.converters.encoders[ + real_datetime + ] diff --git a/freezegun/api.pyi b/freezegun/api.pyi index 8db3c3e0..cd4ced3f 100644 --- a/freezegun/api.pyi +++ b/freezegun/api.pyi @@ -1,6 +1,17 @@ from datetime import date, datetime, timedelta from numbers import Real -from typing import Any, Awaitable, Callable, Iterator, Optional, Sequence, Type, TypeVar, Union, overload +from typing import ( + Any, + Awaitable, + Callable, + Iterator, + Optional, + Sequence, + Type, + TypeVar, + Union, + overload, +) _T = TypeVar("_T") _Freezable = Union[str, datetime, date, timedelta] @@ -36,7 +47,9 @@ class _freeze_time: @overload def __call__(self, func: Type[_T]) -> Type[_T]: ... @overload - def __call__(self, func: Callable[..., Awaitable[_T]]) -> Callable[..., Awaitable[_T]]: ... + def __call__( + self, func: Callable[..., Awaitable[_T]] + ) -> Callable[..., Awaitable[_T]]: ... @overload def __call__(self, func: Callable[..., _T]) -> Callable[..., _T]: ... def __enter__(self) -> Any: ... @@ -48,7 +61,9 @@ class _freeze_time: def decorate_callable(self, func: Callable[..., _T]) -> Callable[..., _T]: ... def freeze_time( - time_to_freeze: Optional[Union[_Freezable, Callable[..., _Freezable], Iterator[_Freezable]]] = ..., + time_to_freeze: Optional[ + Union[_Freezable, Callable[..., _Freezable], Iterator[_Freezable]] + ] = ..., tz_offset: Optional[float] = ..., ignore: Optional[Sequence[str]] = ..., tick: Optional[bool] = ..., diff --git a/freezegun/config.py b/freezegun/config.py index 0f669d73..4965b750 100644 --- a/freezegun/config.py +++ b/freezegun/config.py @@ -1,22 +1,21 @@ from typing import List, Optional - DEFAULT_IGNORE_LIST = [ - 'nose.plugins', - 'six.moves', - 'django.utils.six.moves', - 'google.gax', - 'threading', - 'Queue', - 'selenium', - '_pytest.terminal.', - '_pytest.runner.', - 'gi', + "nose.plugins", + "six.moves", + "django.utils.six.moves", + "google.gax", + "threading", + "Queue", + "selenium", + "_pytest.terminal.", + "_pytest.runner.", + "gi", ] class Settings: - def __init__(self, default_ignore_list: Optional[List[str]]=None) -> None: + def __init__(self, default_ignore_list: Optional[List[str]] = None) -> None: self.default_ignore_list = default_ignore_list or DEFAULT_IGNORE_LIST[:] @@ -27,13 +26,21 @@ class ConfigurationError(Exception): pass -def configure(default_ignore_list: Optional[List[str]]=None, extend_ignore_list: Optional[List[str]]=None) -> None: +def configure( + default_ignore_list: Optional[List[str]] = None, + extend_ignore_list: Optional[List[str]] = None, +) -> None: if default_ignore_list is not None and extend_ignore_list is not None: - raise ConfigurationError("Either default_ignore_list or extend_ignore_list might be given, not both") + raise ConfigurationError( + "Either default_ignore_list or extend_ignore_list might be given, not both" + ) if default_ignore_list: settings.default_ignore_list = default_ignore_list if extend_ignore_list: - settings.default_ignore_list = [*settings.default_ignore_list, *extend_ignore_list] + settings.default_ignore_list = [ + *settings.default_ignore_list, + *extend_ignore_list, + ] def reset_config() -> None: diff --git a/pyproject.toml b/pyproject.toml index 2edada0b..254e2875 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,16 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +target-version = ["py36"] + +[tool.isort] +profile = "black" + [tool.mypy] strict = true pretty = true show_column_numbers = true show_error_codes = true show_error_context = true - -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index 0647c003..077094a6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,3 +23,6 @@ python_requires = >=3.6 install_requires = python-dateutil >= 2.7 include_package_data = true + +[flake8] +max-line-length = 88 diff --git a/tests/another_module.py b/tests/another_module.py index 637c889b..5833e37c 100644 --- a/tests/another_module.py +++ b/tests/another_module.py @@ -1,18 +1,18 @@ from datetime import date, datetime -from time import time, localtime, gmtime, strftime +from time import gmtime, localtime, strftime, time from freezegun.api import ( - FakeDatetime, FakeDate, - fake_time, - fake_localtime, + FakeDatetime, fake_gmtime, + fake_localtime, fake_strftime, + fake_time, ) - # Reals + def get_datetime(): return datetime @@ -39,6 +39,7 @@ def get_strftime(): # Fakes + def get_fake_datetime(): return FakeDatetime diff --git a/tests/fake_module.py b/tests/fake_module.py index 8afdaecf..5033fc8a 100644 --- a/tests/fake_module.py +++ b/tests/fake_module.py @@ -1,5 +1,5 @@ from datetime import date, datetime -from time import time, localtime, gmtime, strftime +from time import gmtime, localtime, strftime, time def fake_datetime_function(): @@ -27,7 +27,7 @@ def fake_strftime_function(): class EqualToAnything: - description = 'This is the equal_to_anything object' + description = "This is the equal_to_anything object" def __eq__(self, other): return True diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index db2cdbe8..641b709e 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -8,9 +8,9 @@ def test_time_freeze_coroutine(): if not asyncio: - raise SkipTest('asyncio required') + raise SkipTest("asyncio required") - @freeze_time('1970-01-01') + @freeze_time("1970-01-01") async def frozen_coroutine(): assert datetime.date.today() == datetime.date(1970, 1, 1) @@ -19,13 +19,17 @@ async def frozen_coroutine(): def test_time_freeze_async_def(): try: - exec('async def foo(): pass') + exec("async def foo(): pass") except SyntaxError: - raise SkipTest('async def not supported') + raise SkipTest("async def not supported") else: - exec(dedent(''' + exec( + dedent( + """ @freeze_time('1970-01-01') async def frozen_coroutine(): assert datetime.date.today() == datetime.date(1970, 1, 1) asyncio.get_event_loop().run_until_complete(frozen_coroutine()) - ''')) + """ + ) + ) diff --git a/tests/test_class_import.py b/tests/test_class_import.py index 709dc6e1..4df34fc8 100644 --- a/tests/test_class_import.py +++ b/tests/test_class_import.py @@ -1,5 +1,18 @@ -import time +import datetime import sys +import time + +from freezegun import freeze_time +from freezegun.api import ( + FakeDate, + FakeDatetime, + fake_gmtime, + fake_localtime, + fake_strftime, + fake_time, +) + +from . import fake_module from .fake_module import ( fake_date_function, fake_datetime_function, @@ -8,17 +21,6 @@ fake_strftime_function, fake_time_function, ) -from . import fake_module -from freezegun import freeze_time -from freezegun.api import ( - FakeDatetime, - FakeDate, - fake_time, - fake_localtime, - fake_gmtime, - fake_strftime, -) -import datetime @freeze_time("2012-01-14") @@ -61,7 +63,7 @@ def test_isinstance_works(): date = datetime.date.today() now = datetime.datetime.now() - freezer = freeze_time('2011-01-01') + freezer = freeze_time("2011-01-01") freezer.start() assert isinstance(date, datetime.date) assert not isinstance(date, datetime.datetime) @@ -74,7 +76,7 @@ def test_issubclass_works(): real_date = datetime.date real_datetime = datetime.datetime - freezer = freeze_time('2011-01-01') + freezer = freeze_time("2011-01-01") freezer.start() assert issubclass(real_date, datetime.date) assert issubclass(real_datetime, datetime.datetime) @@ -83,7 +85,7 @@ def test_issubclass_works(): def test_fake_uses_real_when_ignored(): real_time_before = time.time() - with freeze_time('2012-01-14', ignore=['tests.fake_module']): + with freeze_time("2012-01-14", ignore=["tests.fake_module"]): real_time = fake_time_function() real_time_after = time.time() assert real_time_before <= real_time <= real_time_after @@ -91,11 +93,12 @@ def test_fake_uses_real_when_ignored(): def test_can_ignore_email_module(): from email.utils import formatdate - with freeze_time('2012-01-14'): + + with freeze_time("2012-01-14"): faked_date_str = formatdate() before_date_str = formatdate() - with freeze_time('2012-01-14', ignore=['email']): + with freeze_time("2012-01-14", ignore=["email"]): date_str = formatdate() after_date_str = formatdate() @@ -103,9 +106,12 @@ def test_can_ignore_email_module(): assert before_date_str <= date_str <= after_date_str -@freeze_time('2011-01-01') +@freeze_time("2011-01-01") def test_avoid_replacing_equal_to_anything(): - assert fake_module.equal_to_anything.description == 'This is the equal_to_anything object' + assert ( + fake_module.equal_to_anything.description + == "This is the equal_to_anything object" + ) @freeze_time("2012-01-14 12:00:00") @@ -127,12 +133,12 @@ def test_fake_gmtime_function(): @freeze_time("2012-01-14") def test_fake_strftime_function(): - assert fake_strftime_function() == '2012' + assert fake_strftime_function() == "2012" def test_import_after_start(): - with freeze_time('2012-01-14'): - assert 'tests.another_module' not in sys.modules.keys() + with freeze_time("2012-01-14"): + assert "tests.another_module" not in sys.modules.keys() from tests import another_module # Reals @@ -178,9 +184,10 @@ def test_import_after_start(): assert another_module.get_fake_localtime() is fake_localtime assert another_module.get_fake_gmtime() is fake_gmtime assert another_module.get_fake_strftime() is fake_strftime - del sys.modules['tests.another_module'] + del sys.modules["tests.another_module"] + def test_none_as_initial(): with freeze_time() as ft: - ft.move_to('2012-01-14') - assert fake_strftime_function() == '2012' + ft.move_to("2012-01-14") + assert fake_strftime_function() == "2012" diff --git a/tests/test_configure.py b/tests/test_configure.py index f787fb1b..b933023b 100644 --- a/tests/test_configure.py +++ b/tests/test_configure.py @@ -1,4 +1,5 @@ from unittest import mock + import freezegun import freezegun.config @@ -12,15 +13,17 @@ def teardown_function(): def test_default_ignore_list_is_overridden(): - freezegun.configure(default_ignore_list=['threading', 'tensorflow']) + freezegun.configure(default_ignore_list=["threading", "tensorflow"]) - with mock.patch("freezegun.api._freeze_time.__init__", return_value=None) as _freeze_time_init_mock: + with mock.patch( + "freezegun.api._freeze_time.__init__", return_value=None + ) as _freeze_time_init_mock: freezegun.freeze_time("2020-10-06") expected_ignore_list = [ - 'threading', - 'tensorflow', + "threading", + "tensorflow", ] _freeze_time_init_mock.assert_called_once_with( @@ -29,29 +32,32 @@ def test_default_ignore_list_is_overridden(): ignore=expected_ignore_list, tick=False, as_arg=False, - as_kwarg='', + as_kwarg="", auto_tick_seconds=0, ) + def test_extend_default_ignore_list(): - freezegun.configure(extend_ignore_list=['tensorflow']) + freezegun.configure(extend_ignore_list=["tensorflow"]) - with mock.patch("freezegun.api._freeze_time.__init__", return_value=None) as _freeze_time_init_mock: + with mock.patch( + "freezegun.api._freeze_time.__init__", return_value=None + ) as _freeze_time_init_mock: freezegun.freeze_time("2020-10-06") expected_ignore_list = [ - 'nose.plugins', - 'six.moves', - 'django.utils.six.moves', - 'google.gax', - 'threading', - 'Queue', - 'selenium', - '_pytest.terminal.', - '_pytest.runner.', - 'gi', - 'tensorflow', + "nose.plugins", + "six.moves", + "django.utils.six.moves", + "google.gax", + "threading", + "Queue", + "selenium", + "_pytest.terminal.", + "_pytest.runner.", + "gi", + "tensorflow", ] _freeze_time_init_mock.assert_called_once_with( @@ -60,6 +66,6 @@ def test_extend_default_ignore_list(): ignore=expected_ignore_list, tick=False, as_arg=False, - as_kwarg='', + as_kwarg="", auto_tick_seconds=0, ) diff --git a/tests/test_datetimes.py b/tests/test_datetimes.py index ef8cfa72..5a15afdb 100644 --- a/tests/test_datetimes.py +++ b/tests/test_datetimes.py @@ -1,17 +1,16 @@ -import time import calendar import datetime -import unittest import locale -import sys +import time +import unittest from unittest import SkipTest -from dateutil.tz import UTC import pytest -from tests import utils +from dateutil.tz import UTC from freezegun import freeze_time -from freezegun.api import FakeDatetime, FakeDate +from freezegun.api import FakeDate, FakeDatetime +from tests import utils try: import maya @@ -19,10 +18,11 @@ maya = None # time.clock was removed in Python 3.8 -HAS_CLOCK = hasattr(time, 'clock') -HAS_TIME_NS = hasattr(time, 'time_ns') -HAS_MONOTONIC_NS = hasattr(time, 'monotonic_ns') -HAS_PERF_COUNTER_NS = hasattr(time, 'perf_counter_ns') +HAS_CLOCK = hasattr(time, "clock") +HAS_TIME_NS = hasattr(time, "time_ns") +HAS_MONOTONIC_NS = hasattr(time, "monotonic_ns") +HAS_PERF_COUNTER_NS = hasattr(time, "perf_counter_ns") + class temp_locale: """Temporarily change the locale.""" @@ -38,15 +38,16 @@ def __enter__(self): return except locale.Error: pass - msg = 'could not set locale to any of: %s' % ', '.join(self.targets) + msg = "could not set locale to any of: %s" % ", ".join(self.targets) raise SkipTest(msg) def __exit__(self, *args): locale.setlocale(locale.LC_ALL, self.old) + # Small sample of locales where '%x' expands to a dd/mm/yyyy string, # which can cause trouble when parsed with dateutil. -_dd_mm_yyyy_locales = ['da_DK.UTF-8', 'de_DE.UTF-8', 'fr_FR.UTF-8'] +_dd_mm_yyyy_locales = ["da_DK.UTF-8", "de_DE.UTF-8", "fr_FR.UTF-8"] def test_simple_api(): @@ -94,8 +95,9 @@ def test_tz_offset(): def test_timedelta_tz_offset(): - freezer = freeze_time("2012-01-14 03:21:34", - tz_offset=-datetime.timedelta(hours=3, minutes=30)) + freezer = freeze_time( + "2012-01-14 03:21:34", tz_offset=-datetime.timedelta(hours=3, minutes=30) + ) freezer.start() assert datetime.datetime.now() == datetime.datetime(2012, 1, 13, 23, 51, 34) assert datetime.datetime.utcnow() == datetime.datetime(2012, 1, 14, 3, 21, 34) @@ -113,7 +115,7 @@ def test_tz_offset_with_today(): def test_zero_tz_offset_with_time(): # we expect the system to behave like a system with UTC timezone # at the beginning of the Epoch - freezer = freeze_time('1970-01-01') + freezer = freeze_time("1970-01-01") freezer.start() assert datetime.date.today() == datetime.date(1970, 1, 1) assert datetime.datetime.now() == datetime.datetime(1970, 1, 1) @@ -127,7 +129,7 @@ def test_zero_tz_offset_with_time(): def test_tz_offset_with_time(): # we expect the system to behave like a system with UTC-4 timezone # at the beginning of the Epoch (wall clock should be 4 hrs late) - freezer = freeze_time('1970-01-01', tz_offset=-4) + freezer = freeze_time("1970-01-01", tz_offset=-4) freezer.start() assert datetime.date.today() == datetime.date(1969, 12, 31) assert datetime.datetime.now() == datetime.datetime(1969, 12, 31, 20) @@ -153,8 +155,9 @@ def test_time_with_dst(): def test_manual_increment(): - initial_datetime = datetime.datetime(year=1, month=7, day=12, - hour=15, minute=6, second=3) + initial_datetime = datetime.datetime( + year=1, month=7, day=12, hour=15, minute=6, second=3 + ) with freeze_time(initial_datetime) as frozen_datetime: assert frozen_datetime() == initial_datetime @@ -168,8 +171,9 @@ def test_manual_increment(): def test_manual_increment_seconds(): - initial_datetime = datetime.datetime(year=1, month=7, day=12, - hour=15, minute=6, second=3) + initial_datetime = datetime.datetime( + year=1, month=7, day=12, hour=15, minute=6, second=3 + ) with freeze_time(initial_datetime) as frozen_datetime: assert frozen_datetime() == initial_datetime @@ -183,11 +187,13 @@ def test_manual_increment_seconds(): def test_move_to(): - initial_datetime = datetime.datetime(year=1, month=7, day=12, - hour=15, minute=6, second=3) + initial_datetime = datetime.datetime( + year=1, month=7, day=12, hour=15, minute=6, second=3 + ) - other_datetime = datetime.datetime(year=2, month=8, day=13, - hour=14, minute=5, second=0) + other_datetime = datetime.datetime( + year=2, month=8, day=13, hour=14, minute=5, second=0 + ) with freeze_time(initial_datetime) as frozen_datetime: assert frozen_datetime() == initial_datetime @@ -207,15 +213,19 @@ def test_bad_time_argument(): assert False, "Bad values should raise a ValueError" -@pytest.mark.parametrize("func_name, has_func, tick_size", ( - ("monotonic", True, 1.0), - ("monotonic_ns", HAS_MONOTONIC_NS, int(1e9)), - ("perf_counter", True, 1.0), - ("perf_counter_ns", HAS_PERF_COUNTER_NS, int(1e9)),) +@pytest.mark.parametrize( + "func_name, has_func, tick_size", + ( + ("monotonic", True, 1.0), + ("monotonic_ns", HAS_MONOTONIC_NS, int(1e9)), + ("perf_counter", True, 1.0), + ("perf_counter_ns", HAS_PERF_COUNTER_NS, int(1e9)), + ), ) def test_time_monotonic(func_name, has_func, tick_size): - initial_datetime = datetime.datetime(year=1, month=7, day=12, - hour=15, minute=6, second=3) + initial_datetime = datetime.datetime( + year=1, month=7, day=12, hour=15, minute=6, second=3 + ) if not has_func: pytest.skip("%s does not exist in current version" % func_name) @@ -236,7 +246,7 @@ def test_time_monotonic(func_name, has_func, tick_size): def test_time_gmtime(): - with freeze_time('2012-01-14 03:21:34'): + with freeze_time("2012-01-14 03:21:34"): time_struct = time.gmtime() assert time_struct.tm_year == 2012 assert time_struct.tm_mon == 1 @@ -249,21 +259,19 @@ def test_time_gmtime(): assert time_struct.tm_isdst == -1 -@pytest.mark.skipif(not HAS_CLOCK, - reason="time.clock was removed in Python 3.8") +@pytest.mark.skipif(not HAS_CLOCK, reason="time.clock was removed in Python 3.8") def test_time_clock(): - with freeze_time('2012-01-14 03:21:34'): + with freeze_time("2012-01-14 03:21:34"): assert time.clock() == 0 - with freeze_time('2012-01-14 03:21:35'): + with freeze_time("2012-01-14 03:21:35"): assert time.clock() == 1 - with freeze_time('2012-01-14 03:21:36'): + with freeze_time("2012-01-14 03:21:36"): assert time.clock() == 2 class modify_timezone: - def __init__(self, new_timezone): self.new_timezone = new_timezone self.original_timezone = time.timezone @@ -277,7 +285,7 @@ def __exit__(self, *args): def test_time_localtime(): with modify_timezone(-3600): # Set this for UTC-1 - with freeze_time('2012-01-14 03:21:34'): + with freeze_time("2012-01-14 03:21:34"): time_struct = time.localtime() assert time_struct.tm_year == 2012 assert time_struct.tm_mon == 1 @@ -293,21 +301,21 @@ def test_time_localtime(): def test_strftime(): with modify_timezone(0): - with freeze_time('1970-01-01'): + with freeze_time("1970-01-01"): assert time.strftime("%Y") == "1970" def test_real_strftime_fall_through(): this_real_year = datetime.datetime.now().year with freeze_time(): - assert time.strftime('%Y') == str(this_real_year) - assert time.strftime('%Y', (2001, 1, 1, 1, 1, 1, 1, 1, 1)) == '2001' + assert time.strftime("%Y") == str(this_real_year) + assert time.strftime("%Y", (2001, 1, 1, 1, 1, 1, 1, 1, 1)) == "2001" def test_date_object(): frozen_date = datetime.date(year=2012, month=11, day=10) date_freezer = freeze_time(frozen_date) - regular_freezer = freeze_time('2012-11-10') + regular_freezer = freeze_time("2012-11-10") assert date_freezer.time_to_freeze == regular_freezer.time_to_freeze @@ -334,32 +342,38 @@ def test_invalid_type(): def test_datetime_object(): - frozen_datetime = datetime.datetime(year=2012, month=11, day=10, - hour=4, minute=15, second=30) + frozen_datetime = datetime.datetime( + year=2012, month=11, day=10, hour=4, minute=15, second=30 + ) datetime_freezer = freeze_time(frozen_datetime) - regular_freezer = freeze_time('2012-11-10 04:15:30') + regular_freezer = freeze_time("2012-11-10 04:15:30") assert datetime_freezer.time_to_freeze == regular_freezer.time_to_freeze def test_function_object(): - frozen_datetime = datetime.datetime(year=2012, month=11, day=10, - hour=4, minute=15, second=30) - def function(): return frozen_datetime + frozen_datetime = datetime.datetime( + year=2012, month=11, day=10, hour=4, minute=15, second=30 + ) + + def function(): + return frozen_datetime with freeze_time(function): assert frozen_datetime == datetime.datetime.now() def test_lambda_object(): - frozen_datetime = datetime.datetime(year=2012, month=11, day=10, - hour=4, minute=15, second=30) + frozen_datetime = datetime.datetime( + year=2012, month=11, day=10, hour=4, minute=15, second=30 + ) with freeze_time(lambda: frozen_datetime): assert frozen_datetime == datetime.datetime.now() def test_generator_object(): - frozen_datetimes = (datetime.datetime(year=y, month=1, day=1) - for y in range(2010, 2012)) + frozen_datetimes = ( + datetime.datetime(year=y, month=1, day=1) for y in range(2010, 2012) + ) with freeze_time(frozen_datetimes): assert datetime.datetime(2010, 1, 1) == datetime.datetime.now() @@ -373,20 +387,18 @@ def test_generator_object(): def test_maya_datetimes(): if not maya: - raise SkipTest("maya is optional since it's not supported for " - "enough python versions") + raise SkipTest( + "maya is optional since it's not supported for " "enough python versions" + ) with freeze_time(maya.when("October 2nd, 1997")): - assert datetime.datetime.now() == datetime.datetime( - year=1997, - month=10, - day=2 - ) + assert datetime.datetime.now() == datetime.datetime(year=1997, month=10, day=2) def test_old_datetime_object(): - frozen_datetime = datetime.datetime(year=1, month=7, day=12, - hour=15, minute=6, second=3) + frozen_datetime = datetime.datetime( + year=1, month=7, day=12, hour=15, minute=6, second=3 + ) with freeze_time(frozen_datetime): assert datetime.datetime.now() == frozen_datetime @@ -413,14 +425,12 @@ def to_decorate(): class Callable: - def __call__(self, *args, **kws): return (args, kws) @freeze_time("2012-01-14") class Tester: - def test_the_class(self): assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) @@ -431,11 +441,10 @@ def test_class_name_preserved_by_decorator(self): assert self.__class__.__name__ == "Tester" class NotATestClass: - def perform_operation(self): return datetime.date.today() - @freeze_time('2001-01-01') + @freeze_time("2001-01-01") def test_class_decorator_ignores_nested_class(self): not_a_test = self.NotATestClass() assert not_a_test.perform_operation() == datetime.date(2001, 1, 1) @@ -473,7 +482,9 @@ def test_context_manager(): def test_nested_context_manager(): with freeze_time("2012-01-14"): with freeze_time("2012-12-25"): - _assert_datetime_date_and_time_are_all_equal(datetime.datetime(2012, 12, 25)) + _assert_datetime_date_and_time_are_all_equal( + datetime.datetime(2012, 12, 25) + ) _assert_datetime_date_and_time_are_all_equal(datetime.datetime(2012, 1, 14)) assert datetime.datetime.now() > datetime.datetime(2013, 1, 1) @@ -516,24 +527,25 @@ def test_isinstance_without_active(): class TestUnitTestMethodDecorator(unittest.TestCase): - @freeze_time('2013-04-09') + @freeze_time("2013-04-09") def test_method_decorator_works_on_unittest(self): self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today()) - @freeze_time('2013-04-09', as_kwarg='frozen_time') + @freeze_time("2013-04-09", as_kwarg="frozen_time") def test_method_decorator_works_on_unittest_kwarg_frozen_time(self, frozen_time): self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today()) self.assertEqual(datetime.date(2013, 4, 9), frozen_time.time_to_freeze.today()) - @freeze_time('2013-04-09', as_kwarg='hello') + @freeze_time("2013-04-09", as_kwarg="hello") def test_method_decorator_works_on_unittest_kwarg_hello(self, **kwargs): self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today()) - self.assertEqual(datetime.date(2013, 4, 9), kwargs.get('hello').time_to_freeze.today()) + self.assertEqual( + datetime.date(2013, 4, 9), kwargs.get("hello").time_to_freeze.today() + ) -@freeze_time('2013-04-09') +@freeze_time("2013-04-09") class TestUnitTestClassDecorator(unittest.TestCase): - @classmethod def setUpClass(cls): assert datetime.date(2013, 4, 9) == datetime.date.today() @@ -555,7 +567,7 @@ def test_class_name_preserved_by_decorator(self): self.assertEqual(self.__class__.__name__, "TestUnitTestClassDecorator") -@freeze_time('2013-04-09') +@freeze_time("2013-04-09") class TestUnitTestClassDecoratorWithNoSetUpOrTearDown(unittest.TestCase): def test_class_decorator_works_on_unittest(self): self.assertEqual(datetime.date(2013, 4, 9), datetime.date.today()) @@ -573,8 +585,7 @@ def tearDownClass(cls): super().tearDownClass() def test_class_name_preserved_by_decorator(self): - self.assertEqual(self.__class__.__name__, - "TestUnitTestClassDecoratorSubclass") + self.assertEqual(self.__class__.__name__, "TestUnitTestClassDecoratorSubclass") class BaseInheritanceFreezableTests(unittest.TestCase): @@ -594,7 +605,7 @@ def test_time_is_not_frozen(self): self.assertNotEqual(datetime.date(2013, 4, 9), datetime.date.today()) -@freeze_time('2013-04-09') +@freeze_time("2013-04-09") class FrozenInheritedTests(BaseInheritanceFreezableTests): def test_time_is_frozen(self): # In this class, time should be frozen @@ -604,7 +615,7 @@ def test_time_is_frozen(self): class TestOldStyleClasses: def test_direct_method(self): # Make sure old style classes (not inheriting from object) is supported - @freeze_time('2013-04-09') + @freeze_time("2013-04-09") class OldStyleClass: def method(self): return datetime.date.today() @@ -616,7 +627,7 @@ class OldStyleBaseClass: def inherited_method(self): return datetime.date.today() - @freeze_time('2013-04-09') + @freeze_time("2013-04-09") class OldStyleClass(OldStyleBaseClass): pass @@ -669,27 +680,28 @@ def test_freeze_with_timezone_aware_datetime_in_non_utc(): assert utc_now == datetime.datetime(1970, 1, 1, 4) -@freeze_time('2015-01-01') +@freeze_time("2015-01-01") def test_time_with_nested(): from time import time + first = 1420070400.0 second = 1420070760.0 assert time() == first - with freeze_time('2015-01-01T00:06:00'): + with freeze_time("2015-01-01T00:06:00"): assert time() == second -@pytest.mark.parametrize("func_name", - ("monotonic", "perf_counter") -) +@pytest.mark.parametrize("func_name", ("monotonic", "perf_counter")) def test_monotonic_with_nested(func_name): __import__("time", fromlist=[func_name]) - invoke_time_func = lambda: getattr(time, func_name)() - with freeze_time('2015-01-01') as frozen_datetime_1: + def invoke_time_func(): + return getattr(time, func_name)() + + with freeze_time("2015-01-01") as frozen_datetime_1: initial_t1 = invoke_time_func() - with freeze_time('2015-12-25') as frozen_datetime_2: + with freeze_time("2015-12-25") as frozen_datetime_2: initial_t2 = invoke_time_func() frozen_datetime_2.tick() assert invoke_time_func() == initial_t2 + 1 @@ -707,6 +719,7 @@ def test_should_use_real_time(): expected_clock = 0 from freezegun import api + api.call_stack_inspection_limit = 100 # just to increase coverage timestamp_to_convert = 1579602312 @@ -724,7 +737,7 @@ def test_should_use_real_time(): assert calendar.timegm(time.gmtime()) == expected_frozen assert calendar.timegm(time_tuple) == timestamp_to_convert - with freeze_time(frozen, ignore=['_pytest']): + with freeze_time(frozen, ignore=["_pytest"]): assert time.time() != expected_frozen # assert time.localtime() != expected_frozen_local assert time.gmtime() != expected_frozen_gmt @@ -737,8 +750,9 @@ def test_should_use_real_time(): assert calendar.timegm(time_tuple) == timestamp_to_convert -@pytest.mark.skipif(not HAS_TIME_NS, - reason="time.time_ns is present only on 3.7 and above") +@pytest.mark.skipif( + not HAS_TIME_NS, reason="time.time_ns is present only on 3.7 and above" +) def test_time_ns(): freezer = freeze_time("2012-01-14") local_time = datetime.datetime(2012, 1, 14) @@ -755,8 +769,8 @@ def test_time_ns(): def test_compare_datetime_and_time_with_timezone(monkeypatch): """ - Compare the result of datetime.datetime.now() and time.time() in a non-UTC timezone. These - should be consistent. + Compare the result of datetime.datetime.now() and time.time() in a non-UTC + timezone. These should be consistent. """ try: with monkeypatch.context() as m, freeze_time("1970-01-01 00:00:00"): @@ -785,11 +799,13 @@ def test_timestamp_with_tzoffset(): assert utcnow == datetime.datetime.utcfromtimestamp(time.time()) assert utcnow == datetime.datetime.utcnow() + @pytest.mark.skip("timezone handling is currently incorrect") def test_datetime_in_timezone(monkeypatch): """ - It is assumed that the argument passed to freeze_time is in UTC, unless explicitly indicated - otherwise. Therefore datetime.now() should return the frozen time with an offset. + It is assumed that the argument passed to freeze_time is in UTC, unless + explicitly indicated otherwise. Therefore datetime.now() should return the + frozen time with an offset. """ try: with monkeypatch.context() as m, freeze_time("1970-01-01 00:00:00"): diff --git a/tests/test_errors.py b/tests/test_errors.py index 06d5b260..8df37502 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -3,6 +3,7 @@ import sys import pytest + from freezegun import freeze_time @@ -19,7 +20,8 @@ class ModuleWithError: See: https://github.com/ipython/ipython/blob/5.8.0/IPython/utils/shimmodule.py#L75 """ - __name__ = 'module_with_error' + + __name__ = "module_with_error" __dict__ = {} def __init__(self, error_type): @@ -37,17 +39,17 @@ def __dir__(self): def assert_module_with_raised_error(error_type): """Install a module into sys.modules that raises an error upon invoking __dir__.""" - module = sys.modules['module_with_error'] = ModuleWithError(error_type) + module = sys.modules["module_with_error"] = ModuleWithError(error_type) try: yield finally: - del sys.modules['module_with_error'] + del sys.modules["module_with_error"] assert module.error_triggered -@pytest.mark.parametrize('error_type', [ImportError, TypeError]) +@pytest.mark.parametrize("error_type", [ImportError, TypeError]) def test_ignore_errors_in_start(error_type): with assert_module_with_raised_error(error_type): freezer = freeze_time(datetime.datetime(2019, 1, 11, 9, 34)) diff --git a/tests/test_import_alias.py b/tests/test_import_alias.py index 1dfc388d..da292ba0 100644 --- a/tests/test_import_alias.py +++ b/tests/test_import_alias.py @@ -1,7 +1,8 @@ -from freezegun import freeze_time from datetime import datetime as datetime_aliased from time import time as time_aliased +from freezegun import freeze_time + @freeze_time("1980-01-01") def test_datetime_alias(): @@ -13,9 +14,8 @@ def test_time_alias(): assert time_aliased() == 0.0 -@freeze_time('2013-04-09') +@freeze_time("2013-04-09") class TestCallOtherFuncInTestClassDecoratorWithAlias: - def test_calls_other_method(self): assert datetime_aliased(2013, 4, 9) == datetime_aliased.today() self.some_other_func() diff --git a/tests/test_operations.py b/tests/test_operations.py index 303a1dc8..a782e793 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -1,7 +1,9 @@ import datetime -from freezegun import freeze_time -from dateutil.relativedelta import relativedelta from datetime import timedelta, tzinfo + +from dateutil.relativedelta import relativedelta + +from freezegun import freeze_time from tests import utils @@ -100,4 +102,3 @@ def test_auto_tick(): first_time = datetime.datetime.now() auto_incremented_time = datetime.datetime.now() assert first_time + datetime.timedelta(seconds=15) == auto_incremented_time - diff --git a/tests/test_pickle.py b/tests/test_pickle.py index 95bce9b5..0bddbaf8 100644 --- a/tests/test_pickle.py +++ b/tests/test_pickle.py @@ -1,5 +1,6 @@ import datetime import pickle + from freezegun import freeze_time diff --git a/tests/test_sqlite3.py b/tests/test_sqlite3.py index e63ff753..e33d1b22 100644 --- a/tests/test_sqlite3.py +++ b/tests/test_sqlite3.py @@ -1,7 +1,8 @@ import datetime -from freezegun import freeze_time import sqlite3 +from freezegun import freeze_time + @freeze_time("2013-01-01") def test_fake_datetime_select(): diff --git a/tests/test_ticking.py b/tests/test_ticking.py index e29ce070..460815a6 100644 --- a/tests/test_ticking.py +++ b/tests/test_ticking.py @@ -1,13 +1,14 @@ import datetime import sys import time - from unittest import mock + import pytest from freezegun import freeze_time from tests import utils + @utils.cpython_only def test_ticking_datetime(): with freeze_time("Jan 14th, 2012", tick=True): @@ -15,23 +16,24 @@ def test_ticking_datetime(): assert datetime.datetime.now() > datetime.datetime(2012, 1, 14) -@pytest.mark.skipif(not hasattr(time, "clock"), - reason="time.clock was removed in Python 3.8") +@pytest.mark.skipif( + not hasattr(time, "clock"), reason="time.clock was removed in Python 3.8" +) @utils.cpython_only def test_ticking_time_clock(): - with freeze_time('2012-01-14 03:21:34', tick=True): + with freeze_time("2012-01-14 03:21:34", tick=True): first = time.clock() time.sleep(0.001) # Deal with potential clock resolution problems - with freeze_time('2012-01-14 03:21:35', tick=True): + with freeze_time("2012-01-14 03:21:35", tick=True): second = time.clock() time.sleep(0.001) # Deal with potential clock resolution problems - with freeze_time('2012-01-14 03:21:36', tick=True): + with freeze_time("2012-01-14 03:21:36", tick=True): third = time.clock() time.sleep(0.001) # Rewind time backwards - with freeze_time('2012-01-14 03:20:00', tick=True): + with freeze_time("2012-01-14 03:20:00", tick=True): fourth = time.clock() time.sleep(0.001) fifth = time.clock() @@ -64,7 +66,8 @@ def test_ticking_time(): @utils.cpython_only_mark -@pytest.mark.parametrize("func_name", +@pytest.mark.parametrize( + "func_name", ("monotonic", "monotonic_ns", "perf_counter", "perf_counter_ns"), ) def test_ticking_monotonic(func_name): @@ -76,7 +79,8 @@ def test_ticking_monotonic(func_name): else: if not hasattr(time, func_name): pytest.skip( - "time.%s does not exist in the current Python version" % func_name) + "time.%s does not exist in the current Python version" % func_name + ) func = getattr(time, func_name) with freeze_time("Jan 14th, 2012, 23:59:59", tick=True): @@ -85,7 +89,7 @@ def test_ticking_monotonic(func_name): assert func() > initial -@mock.patch('freezegun.api._is_cpython', False) +@mock.patch("freezegun.api._is_cpython", False) def test_pypy_compat(): try: freeze_time("Jan 14th, 2012, 23:59:59", tick=True) @@ -95,7 +99,7 @@ def test_pypy_compat(): raise AssertionError("tick=True should error on non-CPython") -@mock.patch('freezegun.api._is_cpython', True) +@mock.patch("freezegun.api._is_cpython", True) def test_non_pypy_compat(): try: freeze_time("Jan 14th, 2012, 23:59:59", tick=True) diff --git a/tests/test_utils.py b/tests/test_utils.py index 603c7910..b6aedc21 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,11 +5,11 @@ from tests import utils -@mock.patch('platform.python_implementation', lambda: 'CPython') +@mock.patch("platform.python_implementation", lambda: "CPython") def test_should_not_skip_cpython(): reload(api) reload(utils) - function_mock = mock.MagicMock(__name__='function') + function_mock = mock.MagicMock(__name__="function") try: utils.cpython_only(function_mock)() except SkipTest: @@ -17,11 +17,11 @@ def test_should_not_skip_cpython(): assert function_mock.called -@mock.patch('platform.python_implementation', lambda: 'not-CPython') +@mock.patch("platform.python_implementation", lambda: "not-CPython") def test_should_skip_non_cpython(): reload(api) reload(utils) - function_mock = mock.MagicMock(__name__='function', skipped=False) + function_mock = mock.MagicMock(__name__="function", skipped=False) try: utils.cpython_only(function_mock)() except SkipTest: diff --git a/tests/test_uuid.py b/tests/test_uuid.py index 08ae8a14..a8c61207 100644 --- a/tests/test_uuid.py +++ b/tests/test_uuid.py @@ -10,8 +10,9 @@ def time_from_uuid(value): """ uvalue = value if isinstance(value, uuid.UUID) else uuid.UUID(value) assert uvalue.version == 1 - return (datetime.datetime(1582, 10, 15) + - datetime.timedelta(microseconds=uvalue.time // 10)) + return datetime.datetime(1582, 10, 15) + datetime.timedelta( + microseconds=uvalue.time // 10 + ) def test_uuid1_future(): diff --git a/tests/test_warnings.py b/tests/test_warnings.py index 5ee32ae4..04f9176e 100644 --- a/tests/test_warnings.py +++ b/tests/test_warnings.py @@ -1,7 +1,6 @@ import contextlib import datetime import sys -import types import warnings from freezegun import freeze_time @@ -20,11 +19,13 @@ class ModuleWithWarning: https://github.com/pytest-dev/py/blob/67987e26aadddbbe7d1ec76c16ea9be346ae9811/py/__init__.py https://github.com/pytest-dev/py/blob/67987e26aadddbbe7d1ec76c16ea9be346ae9811/py/_code/_assertionold.py#L3 - celery.task - the sets module is listed in __all__ in celery.task and freeze_time accesses it: + celery.task - the sets module is listed in __all__ in celery.task and + freeze_time accesses it: https://github.com/celery/celery/blob/46c92025cdec07a4a30ad44901cf66cb27346638/celery/task/__init__.py https://github.com/celery/celery/blob/46c92025cdec07a4a30ad44901cf66cb27346638/celery/task/sets.py """ - __name__ = 'module_with_warning' + + __name__ = "module_with_warning" __dict__ = {} warning_triggered = False counter = 0 @@ -33,20 +34,20 @@ class ModuleWithWarning: def attribute_that_emits_a_warning(self): # Use unique warning messages to avoid messages being only reported once self.__class__.counter += 1 - warnings.warn(f'this is test warning #{self.__class__.counter}') + warnings.warn(f"this is test warning #{self.__class__.counter}") self.warning_triggered = True @contextlib.contextmanager def assert_module_with_emitted_warning(): """Install a module that triggers warnings into sys.modules and ensure the - warning was triggered in the with-block. """ - module = sys.modules['module_with_warning'] = ModuleWithWarning() + warning was triggered in the with-block.""" + module = sys.modules["module_with_warning"] = ModuleWithWarning() try: yield finally: - del sys.modules['module_with_warning'] + del sys.modules["module_with_warning"] assert module.warning_triggered @@ -55,7 +56,7 @@ def assert_module_with_emitted_warning(): def assert_no_warnings(): """A context manager that makes sure no warnings was emitted.""" with warnings.catch_warnings(record=True) as caught_warnings: - warnings.filterwarnings('always') + warnings.filterwarnings("always") yield assert not caught_warnings diff --git a/tests/utils.py b/tests/utils.py index 6cb8a235..b23644d0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,10 +1,10 @@ from functools import wraps from unittest import SkipTest -from freezegun.api import FakeDate, FakeDatetime, _is_cpython - import pytest +from freezegun.api import FakeDate, FakeDatetime, _is_cpython + def is_fake_date(obj): return obj.__class__ is FakeDate @@ -14,9 +14,7 @@ def is_fake_datetime(obj): return obj.__class__ is FakeDatetime -cpython_only_mark = pytest.mark.skipif( - not _is_cpython, - reason="Requires CPython") +cpython_only_mark = pytest.mark.skipif(not _is_cpython, reason="Requires CPython") def cpython_only(func): @@ -25,4 +23,5 @@ def wrapper(*args): if not _is_cpython: raise SkipTest("Requires CPython") return func(*args) + return wrapper diff --git a/tox.ini b/tox.ini index 917e9368..49120172 100644 --- a/tox.ini +++ b/tox.ini @@ -4,12 +4,23 @@ # and then run "tox" from this directory. [tox] -envlist = py36, py37, py38, py39, pypy3, mypy +envlist = lint, mypy, py36, py37, py38, py39, pypy3 [testenv] commands = pytest --cov {posargs} deps = -rrequirements.txt +[testenv:lint] +deps = + black + flake8 + isort +commands = + black --check --diff . + flake8 + isort --check --diff . +skip_install = true + [testenv:mypy] deps = mypy