diff -Nru freezegun-0.3.9/AUTHORS.rst freezegun-0.3.10/AUTHORS.rst --- freezegun-0.3.9/AUTHORS.rst 2016-10-13 03:00:44.000000000 +0000 +++ freezegun-0.3.10/AUTHORS.rst 2018-03-06 01:15:53.000000000 +0000 @@ -13,3 +13,4 @@ - `Zach Smith `_ - `Adam Johnson `_ - `Alex Ehlke `_ +- `James Lu `_ diff -Nru freezegun-0.3.9/CHANGELOG freezegun-0.3.10/CHANGELOG --- freezegun-0.3.9/CHANGELOG 2017-05-13 00:24:21.000000000 +0000 +++ freezegun-0.3.10/CHANGELOG 2018-03-06 02:53:53.000000000 +0000 @@ -4,6 +4,13 @@ Latest ------ +0.3.10 +------ + +* Performance improvements +* Coroutine support +* + 0.3.9 ----- diff -Nru freezegun-0.3.9/debian/changelog freezegun-0.3.10/debian/changelog --- freezegun-0.3.9/debian/changelog 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/changelog 2018-11-15 19:27:14.000000000 +0000 @@ -1,3 +1,21 @@ +freezegun (0.3.10-2~cloud0) bionic-stein; urgency=medium + + * New upstream release for the Ubuntu Cloud Archive. + + -- Openstack Ubuntu Testing Bot Thu, 15 Nov 2018 19:27:14 +0000 + +freezegun (0.3.10-2) unstable; urgency=medium + + * Do not install freezegun/_async.py for Python 2 + + -- Federico Ceratto Tue, 28 Aug 2018 17:25:00 +0100 + +freezegun (0.3.10-1) unstable; urgency=medium + + * New upstream release (Closes: #907350) + + -- Federico Ceratto Sun, 26 Aug 2018 22:46:18 +0100 + freezegun (0.3.9-1) unstable; urgency=medium * New upstream release diff -Nru freezegun-0.3.9/debian/compat freezegun-0.3.10/debian/compat --- freezegun-0.3.9/debian/compat 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/compat 2018-08-28 16:25:00.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru freezegun-0.3.9/debian/control freezegun-0.3.10/debian/control --- freezegun-0.3.9/debian/control 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/control 2018-08-28 16:25:00.000000000 +0000 @@ -2,7 +2,7 @@ Section: python Priority: optional Maintainer: Federico Ceratto -Build-Depends: debhelper (>= 10~) +Build-Depends: debhelper (>= 11~) Build-Depends-Indep: dh-python, python-all (>= 2.6.6-3~), @@ -17,10 +17,10 @@ python3-mock, python3-nose, python3-setuptools, -Standards-Version: 4.1.1 +Standards-Version: 4.2.1 Homepage: https://github.com/spulec/freezegun -Vcs-Git: https://anonscm.debian.org/git/collab-maint/python-freezegun.git -Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/python-freezegun.git +Vcs-Git: https://salsa.debian.org/debian/python-freezegun.git +Vcs-Browser: https://salsa.debian.org/debian/python-freezegun X-Python-Version: >= 2.7 X-Python3-Version: >= 3.2 diff -Nru freezegun-0.3.9/debian/copyright freezegun-0.3.10/debian/copyright --- freezegun-0.3.9/debian/copyright 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/copyright 2018-08-28 16:25:00.000000000 +0000 @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: freezegun Source: https://github.com/spulec/freezegun diff -Nru freezegun-0.3.9/debian/gitlab-ci.yml freezegun-0.3.10/debian/gitlab-ci.yml --- freezegun-0.3.9/debian/gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ freezegun-0.3.10/debian/gitlab-ci.yml 2018-08-28 16:25:00.000000000 +0000 @@ -0,0 +1,10 @@ +image: registry.gitlab.com/eighthave/ci-image-git-buildpackage:latest + +pages: + stage: deploy + artifacts: + paths: + - "*.deb" + script: + - gitlab-ci-git-buildpackage-all + - gitlab-ci-aptly diff -Nru freezegun-0.3.9/debian/rules freezegun-0.3.10/debian/rules --- freezegun-0.3.9/debian/rules 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/rules 2018-08-28 16:25:00.000000000 +0000 @@ -22,5 +22,9 @@ done endif +override_dh_auto_install: + dh_auto_install + rm -rf $(CURDIR)/debian/python-freezegun/usr/lib/python2.*/dist-packages/freezegun/_async.py + override_dh_installchangelogs: dh_installchangelogs CHANGELOG diff -Nru freezegun-0.3.9/debian/watch freezegun-0.3.10/debian/watch --- freezegun-0.3.9/debian/watch 2017-10-03 11:22:52.000000000 +0000 +++ freezegun-0.3.10/debian/watch 2018-08-28 16:25:00.000000000 +0000 @@ -1,3 +1,3 @@ version=3 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \ -http://pypi.debian.net/freezegun/freezegun-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) +https://pypi.debian.net/freezegun/freezegun-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -Nru freezegun-0.3.9/freezegun/api.py freezegun-0.3.10/freezegun/api.py --- freezegun-0.3.9/freezegun/api.py 2017-02-09 03:47:40.000000000 +0000 +++ freezegun-0.3.10/freezegun/api.py 2018-03-06 02:31:33.000000000 +0000 @@ -1,5 +1,6 @@ import datetime import functools +import hashlib import inspect import sys import time @@ -8,6 +9,8 @@ import unittest import platform import warnings +import types +import numbers from dateutil import parser from dateutil.tz import tzlocal @@ -18,15 +21,18 @@ real_strftime = time.strftime real_date = datetime.date real_datetime = datetime.datetime +real_date_objects = [real_time, real_localtime, real_gmtime, real_strftime, real_date, real_datetime] +_real_time_object_ids = set(id(obj) for obj in real_date_objects) + try: real_uuid_generate_time = uuid._uuid_generate_time -except ImportError: +except (AttributeError, ImportError): real_uuid_generate_time = None try: real_uuid_create = uuid._UuidCreate -except ImportError: +except (AttributeError, ImportError): real_uuid_create = None try: @@ -34,6 +40,79 @@ except ImportError: import copyreg +try: + iscoroutinefunction = inspect.iscoroutinefunction + from freezegun._async import wrap_coroutine +except AttributeError: + iscoroutinefunction = lambda x: False + + def wrap_coroutine(*args): + raise NotImplementedError() + + +# keep a cache of module attributes otherwise freezegun will need to analyze too many modules all the time +# start with `None` as the sentinel value. +# if `{}` (empty dict) was the sentinel value, there's a chance that `setup_modules_cache()` will be called many times +_GLOBAL_MODULES_CACHE = None + + +def _get_global_modules_cache(): + global _GLOBAL_MODULES_CACHE + # the first call to this function sets up the global module cache. it's expected to be slower than consecutive calls + if _GLOBAL_MODULES_CACHE is None: + _GLOBAL_MODULES_CACHE = {} + _setup_modules_cache() + return _GLOBAL_MODULES_CACHE + + +def _get_module_attributes(module): + result = [] + try: + module_attributes = dir(module) + except TypeError: + return result + for attribute_name in module_attributes: + try: + attribute_value = getattr(module, attribute_name) + except (ImportError, AttributeError, TypeError): + # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery) + continue + else: + result.append((attribute_name, attribute_value)) + return result + + +def _setup_modules_cache(): + for mod_name, module in list(sys.modules.items()): + # ignore modules from freezegun + if mod_name == __name__ or not mod_name or not module or not hasattr(module, "__name__"): + continue + _setup_module_cache(module) + + +def _setup_module_cache(module): + global _GLOBAL_MODULES_CACHE + date_attrs = [] + all_module_attributes = _get_module_attributes(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) + + +def _get_module_attributes_hash(module): + return '{0}-{1}'.format(id(module), hashlib.md5(','.join(dir(module)).encode('utf-8')).hexdigest()) + + +def _get_cached_module_attributes(mod_name, module): + global_modules_cache = _get_global_modules_cache() + module_hash, cached_attrs = global_modules_cache.get(mod_name, ('0', [])) + if _get_module_attributes_hash(module) == module_hash: + return cached_attrs + else: + _setup_module_cache(module) + return _get_module_attributes(module) + # Stolen from six def with_metaclass(meta, *bases): @@ -138,7 +217,7 @@ @classmethod def today(cls): - result = cls._date_to_freeze() + datetime.timedelta(hours=cls._tz_offset()) + result = cls._date_to_freeze() + cls._tz_offset() return date_to_fakedate(result) @classmethod @@ -190,9 +269,9 @@ def now(cls, tz=None): now = cls._time_to_freeze() or real_datetime.now() if tz: - result = tz.fromutc(now.replace(tzinfo=tz)) + datetime.timedelta(hours=cls._tz_offset()) + result = tz.fromutc(now.replace(tzinfo=tz)) + cls._tz_offset() else: - result = now + datetime.timedelta(hours=cls._tz_offset()) + result = now + cls._tz_offset() return datetime_to_fakedatetime(result) def date(self): @@ -270,6 +349,13 @@ return convert_to_timezone_naive(time_to_freeze) +def _parse_tz_offset(tz_offset): + if isinstance(tz_offset, datetime.timedelta): + return tz_offset + else: + return datetime.timedelta(hours=tz_offset) + + class TickingDateTimeFactory(object): def __init__(self, time_to_freeze, start): @@ -289,7 +375,10 @@ return self.time_to_freeze def tick(self, delta=datetime.timedelta(seconds=1)): - self.time_to_freeze += delta + if isinstance(delta, numbers.Real): + self.time_to_freeze += datetime.timedelta(seconds=delta) + else: + self.time_to_freeze += delta def move_to(self, target_datetime): """Moves frozen date to the given ``target_datetime``""" @@ -300,18 +389,21 @@ class _freeze_time(object): - def __init__(self, time_to_freeze_str, tz_offset, ignore, tick): + def __init__(self, time_to_freeze_str, tz_offset, ignore, tick, as_arg): self.time_to_freeze = _parse_time_to_freeze(time_to_freeze_str) - self.tz_offset = tz_offset + self.tz_offset = _parse_tz_offset(tz_offset) self.ignore = tuple(ignore) self.tick = tick self.undo_changes = [] self.modules_at_start = set() + self.as_arg = as_arg def __call__(self, func): if inspect.isclass(func): return self.decorate_class(func) + elif iscoroutinefunction(func): + return self.decorate_coroutine(func) return self.decorate_callable(func) def decorate_class(self, klass): @@ -375,7 +467,13 @@ # Change the modules datetime.datetime = FakeDatetime + datetime.datetime.times_to_freeze.append(time_to_freeze) + datetime.datetime.tz_offsets.append(self.tz_offset) + datetime.date = FakeDate + datetime.date.dates_to_freeze.append(time_to_freeze) + datetime.date.tz_offsets.append(self.tz_offset) + fake_time = FakeTime(time_to_freeze, time.time) fake_localtime = FakeLocalTime(time_to_freeze, time.localtime) fake_gmtime = FakeGMTTime(time_to_freeze, time.gmtime) @@ -386,6 +484,7 @@ time.strftime = fake_strftime uuid._uuid_generate_time = None uuid._UuidCreate = None + uuid._last_timestamp = None copyreg.dispatch_table[real_datetime] = pickle_fake_datetime copyreg.dispatch_table[real_date] = pickle_fake_date @@ -399,7 +498,6 @@ ('real_strftime', real_strftime, 'FakeStrfTime', fake_strftime), ('real_time', real_time, 'FakeTime', fake_time), ] - real_names = tuple(real_name for real_name, real, fake_name, fake in to_patch) self.fake_names = tuple(fake_name for real_name, real, fake_name, fake in to_patch) self.reals = dict((id(fake), real) for real_name, real, fake_name, fake in to_patch) fakes = dict((id(real), fake) for real_name, real, fake_name, fake in to_patch) @@ -412,30 +510,19 @@ warnings.filterwarnings('ignore') for mod_name, module in list(sys.modules.items()): - if mod_name is None or module is None: + if mod_name is None or module is None or mod_name == __name__: continue - elif mod_name.startswith(self.ignore): + elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'): continue elif (not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time')): continue - for module_attribute in dir(module): - if module_attribute in real_names: - continue - try: - attribute_value = getattr(module, module_attribute) - except (ImportError, AttributeError, TypeError): - # For certain libraries, this can result in ImportError(_winreg) or AttributeError (celery) - continue + + module_attrs = _get_cached_module_attributes(mod_name, module) + for attribute_name, attribute_value in module_attrs: fake = fakes.get(id(attribute_value)) if fake: - setattr(module, module_attribute, fake) - add_change((module, module_attribute, attribute_value)) - - datetime.datetime.times_to_freeze.append(time_to_freeze) - datetime.datetime.tz_offsets.append(self.tz_offset) - - datetime.date.dates_to_freeze.append(time_to_freeze) - datetime.date.tz_offsets.append(self.tz_offset) + setattr(module, attribute_name, fake) + add_change((module, attribute_name, attribute_value)) return time_to_freeze @@ -463,7 +550,7 @@ module = sys.modules.get(mod_name, None) if mod_name is None or module is None: continue - elif mod_name.startswith(self.ignore): + elif mod_name.startswith(self.ignore) or mod_name.endswith('.six.moves'): continue elif (not hasattr(module, "__name__") or module.__name__ in ('datetime', 'time')): continue @@ -488,11 +575,18 @@ uuid._uuid_generate_time = real_uuid_generate_time uuid._UuidCreate = real_uuid_create + uuid._last_timestamp = None + + def decorate_coroutine(self, coroutine): + return wrap_coroutine(self, coroutine) def decorate_callable(self, func): def wrapper(*args, **kwargs): - with self: - result = func(*args, **kwargs) + with self as time_factory: + if self.as_arg: + result = func(time_factory, *args, **kwargs) + else: + result = func(*args, **kwargs) return result functools.update_wrapper(wrapper, func) @@ -503,26 +597,34 @@ return wrapper -def freeze_time(time_to_freeze=None, tz_offset=0, ignore=None, tick=False): +def freeze_time(time_to_freeze=None, tz_offset=0, ignore=None, tick=False, as_arg=False): # Python3 doesn't have basestring, but it does have str. try: string_type = basestring except NameError: string_type = str - if not isinstance(time_to_freeze, (type(None), string_type, datetime.date)): - raise TypeError(('freeze_time() expected None, a string, date instance, or ' - 'datetime instance, but got type {0}.').format(type(time_to_freeze))) + if not isinstance(time_to_freeze, (type(None), string_type, datetime.date, + types.FunctionType, types.GeneratorType)): + raise TypeError(('freeze_time() expected None, a string, date instance, datetime ' + 'instance, function or a generator, but got type {0}.').format(type(time_to_freeze))) if tick and not _is_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) + + if isinstance(time_to_freeze, types.GeneratorType): + return freeze_time(next(time_to_freeze), tz_offset, ignore, tick) + if ignore is None: ignore = [] ignore.append('six.moves') ignore.append('django.utils.six.moves') + ignore.append('google.gax') ignore.append('threading') ignore.append('Queue') - return _freeze_time(time_to_freeze, tz_offset, ignore, tick) + return _freeze_time(time_to_freeze, tz_offset, ignore, tick, as_arg) # Setup adapters for sqlite diff -Nru freezegun-0.3.9/freezegun/_async.py freezegun-0.3.10/freezegun/_async.py --- freezegun-0.3.9/freezegun/_async.py 1970-01-01 00:00:00.000000000 +0000 +++ freezegun-0.3.10/freezegun/_async.py 2018-03-06 02:30:32.000000000 +0000 @@ -0,0 +1,17 @@ +import functools + +import asyncio + + +def wrap_coroutine(api, coroutine): + @functools.wraps(coroutine) + @asyncio.coroutine + def wrapper(*args, **kwargs): + with api as time_factory: + if api.as_arg: + result = yield from coroutine(time_factory, *args, **kwargs) + else: + result = yield from coroutine(*args, **kwargs) + return result + + return wrapper diff -Nru freezegun-0.3.9/freezegun/__init__.py freezegun-0.3.10/freezegun/__init__.py --- freezegun-0.3.9/freezegun/__init__.py 2017-05-13 00:24:30.000000000 +0000 +++ freezegun-0.3.10/freezegun/__init__.py 2018-03-06 02:54:23.000000000 +0000 @@ -9,7 +9,7 @@ from .api import freeze_time __title__ = 'freezegun' -__version__ = '0.3.9' +__version__ = '0.3.10' __author__ = 'Steve Pulec' __license__ = 'Apache License 2.0' __copyright__ = 'Copyright 2012 Steve Pulec' diff -Nru freezegun-0.3.9/freezegun.egg-info/PKG-INFO freezegun-0.3.10/freezegun.egg-info/PKG-INFO --- freezegun-0.3.9/freezegun.egg-info/PKG-INFO 2017-05-13 00:25:54.000000000 +0000 +++ freezegun-0.3.10/freezegun.egg-info/PKG-INFO 2018-03-06 02:54:52.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: freezegun -Version: 0.3.9 +Version: 0.3.10 Summary: Let your Python tests travel through time Home-page: https://github.com/spulec/freezegun Author: Steve Pulec Author-email: spulec@gmail.com License: Apache 2.0 +Description-Content-Type: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: License :: OSI Approved :: Apache Software License @@ -14,3 +15,5 @@ Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.6 diff -Nru freezegun-0.3.9/freezegun.egg-info/requires.txt freezegun-0.3.10/freezegun.egg-info/requires.txt --- freezegun-0.3.9/freezegun.egg-info/requires.txt 2017-05-13 00:25:54.000000000 +0000 +++ freezegun-0.3.10/freezegun.egg-info/requires.txt 2018-03-06 02:54:52.000000000 +0000 @@ -1,2 +1,2 @@ six -python-dateutil>=1.0, != 2.0 +python-dateutil!=2.0,>=1.0 diff -Nru freezegun-0.3.9/freezegun.egg-info/SOURCES.txt freezegun-0.3.10/freezegun.egg-info/SOURCES.txt --- freezegun-0.3.9/freezegun.egg-info/SOURCES.txt 2017-05-13 00:25:54.000000000 +0000 +++ freezegun-0.3.10/freezegun.egg-info/SOURCES.txt 2018-03-06 02:54:52.000000000 +0000 @@ -6,6 +6,7 @@ setup.cfg setup.py freezegun/__init__.py +freezegun/_async.py freezegun/api.py freezegun.egg-info/PKG-INFO freezegun.egg-info/SOURCES.txt @@ -15,6 +16,7 @@ tests/__init__.py tests/another_module.py tests/fake_module.py +tests/test_asyncio.py tests/test_class_import.py tests/test_datetimes.py tests/test_import_alias.py diff -Nru freezegun-0.3.9/PKG-INFO freezegun-0.3.10/PKG-INFO --- freezegun-0.3.9/PKG-INFO 2017-05-13 00:25:54.000000000 +0000 +++ freezegun-0.3.10/PKG-INFO 2018-03-06 02:54:52.000000000 +0000 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: freezegun -Version: 0.3.9 +Version: 0.3.10 Summary: Let your Python tests travel through time Home-page: https://github.com/spulec/freezegun Author: Steve Pulec Author-email: spulec@gmail.com License: Apache 2.0 +Description-Content-Type: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: License :: OSI Approved :: Apache Software License @@ -14,3 +15,5 @@ Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.6 diff -Nru freezegun-0.3.9/README.rst freezegun-0.3.10/README.rst --- freezegun-0.3.9/README.rst 2017-01-19 03:53:16.000000000 +0000 +++ freezegun-0.3.10/README.rst 2018-03-06 02:30:32.000000000 +0000 @@ -82,6 +82,10 @@ # datetime.date.today() uses local time assert datetime.date.today() == datetime.date(2012, 1, 13) + @freeze_time("2012-01-14 03:21:34", tz_offset=-datetime.timedelta(hours=3, minutes=30)) + def test_timedelta_offset(): + assert datetime.datetime.now() == datetime.datetime(2012, 1, 13, 23, 51, 34) + Nice inputs ~~~~~~~~~~~ @@ -93,6 +97,28 @@ def test_nice_datetime(): assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) +Function and generator objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +FreezeGun is able to handle function and generator objects. + +.. code-block:: python + + def test_lambda(): + with freeze_time(lambda: datetime.datetime(2012, 1, 14)): + assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) + + def test_generator(): + datetimes = (datetime.datetime(year, 1, 1) for year in range(2010, 2012)) + + with freeze_time(datetimes): + assert datetime.datetime.now() == datetime.datetime(2010, 1, 1) + + with freeze_time(datetimes): + assert datetime.datetime.now() == datetime.datetime(2011, 1, 1) + + # The next call to freeze_time(datetimes) would raise a StopIteration exception. + ``tick`` argument ~~~~~~~~~~~~~~~~~ @@ -149,6 +175,13 @@ frozen_datetime.move_to(initial_datetime) assert frozen_datetime() == initial_datetime + + @freeze_time("2012-01-14", as_arg=True) + def test(frozen_time): + assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) + frozen_time.move_to("2014-02-12") + assert datetime.datetime.now() == datetime.datetime(2014, 2, 12) + Parameter for ``move_to`` can be any valid ``freeze_time`` date (string, date, datetime). diff -Nru freezegun-0.3.9/setup.cfg freezegun-0.3.10/setup.cfg --- freezegun-0.3.9/setup.cfg 2017-05-13 00:25:54.000000000 +0000 +++ freezegun-0.3.10/setup.cfg 2018-03-06 02:54:52.000000000 +0000 @@ -10,5 +10,4 @@ [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -Nru freezegun-0.3.9/setup.py freezegun-0.3.10/setup.py --- freezegun-0.3.9/setup.py 2017-05-13 00:25:46.000000000 +0000 +++ freezegun-0.3.10/setup.py 2018-03-06 02:54:04.000000000 +0000 @@ -11,10 +11,14 @@ # Py3k requires += ['python-dateutil>=2.0'] +with open('README.rst') as f: + readme = f.read() + setup( name='freezegun', - version='0.3.9', + version='0.3.10', description='Let your Python tests travel through time', + long_desciption=readme, author='Steve Pulec', author_email='spulec@gmail.com', url='https://github.com/spulec/freezegun', @@ -29,5 +33,7 @@ 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.6', ], ) diff -Nru freezegun-0.3.9/tests/test_asyncio.py freezegun-0.3.10/tests/test_asyncio.py --- freezegun-0.3.9/tests/test_asyncio.py 1970-01-01 00:00:00.000000000 +0000 +++ freezegun-0.3.10/tests/test_asyncio.py 2018-03-06 02:30:32.000000000 +0000 @@ -0,0 +1,36 @@ +import datetime +from textwrap import dedent + +from nose.plugins import skip + +from freezegun import freeze_time + +try: + import asyncio +except ImportError: + asyncio = False + + +def test_time_freeze_coroutine(): + if not asyncio: + raise skip.SkipTest('asyncio required') + @asyncio.coroutine + @freeze_time('1970-01-01') + def frozen_coroutine(): + assert datetime.date.today() == datetime.date(1970, 1, 1) + + asyncio.get_event_loop().run_until_complete(frozen_coroutine()) + + +def test_time_freeze_async_def(): + try: + exec('async def foo(): pass') + except SyntaxError: + raise skip.SkipTest('async def not supported') + else: + 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 -Nru freezegun-0.3.9/tests/test_datetimes.py freezegun-0.3.10/tests/test_datetimes.py --- freezegun-0.3.9/tests/test_datetimes.py 2016-11-06 14:56:38.000000000 +0000 +++ freezegun-0.3.10/tests/test_datetimes.py 2018-03-06 02:30:32.000000000 +0000 @@ -5,6 +5,7 @@ import sys from nose.plugins import skip +from nose.tools import assert_raises from tests import utils from freezegun import freeze_time @@ -76,6 +77,15 @@ freezer.stop() +def test_timedelta_tz_offset(): + 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) + freezer.stop() + + def test_tz_offset_with_today(): freezer = freeze_time("2012-01-14", tz_offset=-4) freezer.start() @@ -137,6 +147,21 @@ assert frozen_datetime() == initial_datetime +def test_manual_increment_seconds(): + 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 + + frozen_datetime.tick() + initial_datetime += datetime.timedelta(seconds=1) + assert frozen_datetime() == initial_datetime + + frozen_datetime.tick(10) + initial_datetime += datetime.timedelta(seconds=10) + assert frozen_datetime() == initial_datetime + + def test_move_to(): initial_datetime = datetime.datetime(year=1, month=7, day=12, hour=15, minute=6, second=3) @@ -248,6 +273,35 @@ 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 + + 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) + 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)) + + with freeze_time(frozen_datetimes): + assert datetime.datetime(2010, 1, 1) == datetime.datetime.now() + + with freeze_time(frozen_datetimes): + assert datetime.datetime(2011, 1, 1) == datetime.datetime.now() + + assert_raises(StopIteration, freeze_time, frozen_datetimes) + + def test_old_datetime_object(): frozen_datetime = datetime.datetime(year=1, month=7, day=12, hour=15, minute=6, second=3) diff -Nru freezegun-0.3.9/tests/test_uuid.py freezegun-0.3.10/tests/test_uuid.py --- freezegun-0.3.9/tests/test_uuid.py 2017-02-09 03:47:40.000000000 +0000 +++ freezegun-0.3.10/tests/test_uuid.py 2018-03-06 02:30:32.000000000 +0000 @@ -1,24 +1,46 @@ +from __future__ import print_function, absolute_import, unicode_literals import datetime import uuid +from nose.tools import assert_equal + from freezegun import freeze_time def time_from_uuid(value): - """Converts an UUID(1) to it's datetime value""" + """ + Converts an UUID(1) to it's datetime 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)) -def test_uuid1(): - # Test that the uuid.uuid1() methods generate a value from the freezed date - # This was not always the case as python is - # using the system's one if available through ctypes - target = datetime.datetime(2017, 2, 6, 14, 8, 21) - - with freeze_time(target): - assert time_from_uuid(uuid.uuid1()) == target +def test_uuid1_future(): + """ + Test that we can go back in time after setting a future date. + Normally UUID1 would disallow this, since it keeps track of + the _last_timestamp, but we override that now. + """ + future_target = datetime.datetime(2056, 2, 6, 14, 3, 21) + with freeze_time(future_target): + assert_equal(time_from_uuid(uuid.uuid1()), future_target) + + past_target = datetime.datetime(1978, 7, 6, 23, 6, 31) + with freeze_time(past_target): + assert_equal(time_from_uuid(uuid.uuid1()), past_target) + + +def test_uuid1_past(): + """ + Test that we can go forward in time after setting some time in the past. + This is simply the opposite of test_uuid1_future() + """ + past_target = datetime.datetime(1978, 7, 6, 23, 6, 31) + with freeze_time(past_target): + assert_equal(time_from_uuid(uuid.uuid1()), past_target) + + future_target = datetime.datetime(2056, 2, 6, 14, 3, 21) + with freeze_time(future_target): + assert_equal(time_from_uuid(uuid.uuid1()), future_target)