spulec / freezegun Goto Github PK
View Code? Open in Web Editor NEWLet your Python tests travel through time
License: Apache License 2.0
Let your Python tests travel through time
License: Apache License 2.0
Freezegun doesn't affect time.strptime, which still returns the current time. I know you don't claim to affect this method in the README, but it might but helpful to others if you could mention explicitly that you don't:
import unittest
import time
from freezegun import freeze_time
class TestStrptime(unittest.TestCase):
@freeze_time("2012-01-14 12:00:01")
def test_strptime(self):
self.assertEquals(time.strftime("%Y"), "2012")
I'm interested in adding a feature for the sleep(seconds) built-in function being mocked to increment the frozen time by seconds. This simulates the affect of sleep in the real world, obviously without having to actually wait.
Would this violate the spirit of freezegun, or would you be likely to support such a feature?
Hi,
I run into a performance issue with 0.2.3 version. 0.2.2 works just fine.
Below the sample from profiler output for test function. Also the profiler shows muchbigger output for 0.2.3.
from freezegun import freeze_time
import datetime
def test():
with freeze_time('2014-10-10'):
print datetime.datetime.now()
0.2.3:
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.010 0.010 0.395 0.395 api.py:264(stop)
1 0.009 0.009 0.448 0.448 api.py:223(start)
1 0.000 0.000 0.395 0.395 api.py:220(__exit__)
1 0.000 0.000 0.448 0.448 api.py:217(__enter__)
0.2.2:
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 0.003 0.003 api.py:223(start)
1 0.001 0.001 0.002 0.002 api.py:255(stop)
1 0.000 0.000 0.002 0.002 api.py:220(__exit__)
1 0.000 0.000 0.003 0.003 api.py:217(__enter__)
If you have a date object that was created before freezing time, you cannot then do an isinstance check against datetime.date:
>>> date = datetime.date.today()
>>> freezer = freeze_time('2011-01-01')
>>> freezer.start()
>>> isinstance(date, datetime.date)
False
>>>
This is because at the point you call the isinstance, the value of datetime.date is <class 'freezegun.api.FakeDate'>
, of which date
is not a subclass.
Pickle library won't support the mock datetime objects:
In [1]: from freezegun import freeze_time
In [2]: import datetime
In [3]: import pickle
In [4]: import StringIO
In [5]: freezer = freeze_time("2012-12-12")
In [6]: freezer.start()
In [7]: f=StringIO.StringIO()
In [8]: pickle.dump(datetime.datetime.now(), f)
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (156, 0))
---------------------------------------------------------------------------
PicklingError Traceback (most recent call last)
/vagrant/<ipython console> in <module>()
/usr/lib/python2.7/pickle.pyc in dump(obj, file, protocol)
1368
1369 def dump(obj, file, protocol=None):
-> 1370 Pickler(file, protocol).dump(obj)
1371
1372 def dumps(obj, protocol=None):
/usr/lib/python2.7/pickle.pyc in dump(self, obj)
222 if self.proto >= 2:
223 self.write(PROTO + chr(self.proto))
--> 224 self.save(obj)
225 self.write(STOP)
226
/usr/lib/python2.7/pickle.pyc in save(self, obj)
329
330 # Save the reduce() output and finally memoize the object
--> 331 self.save_reduce(obj=obj, *rv)
332
333 def persistent_id(self, obj):
/usr/lib/python2.7/pickle.pyc in save_reduce(self, func, args, state, listitems, dictitems, obj)
398 write(NEWOBJ)
399 else:
--> 400 save(func)
401 save(args)
402 write(REDUCE)
/usr/lib/python2.7/pickle.pyc in save(self, obj)
284 f = self.dispatch.get(t)
285 if f:
--> 286 f(self, obj) # Call unbound method with explicit self
287 return
288
/usr/lib/python2.7/pickle.pyc in save_global(self, obj, name, pack)
751 raise PicklingError(
752 "Can't pickle %r: it's not the same object as %s.%s" %
--> 753 (obj, module, name))
754
755 if self.proto >= 2:
PicklingError: Can't pickle <type 'datetime.datetime'>: it's not the same object as datetime.datetime
Wanted to use this but I get bizarre errors from Pandas when I add the decorator to my test function.
The test and the code being tested do not execute any Pandas methods directly, but one of my project modules imports pandas - the error is occurring at import time.
File "/Users/anentropic/Documents/Dev/Work/anentropic/backend/stats/users.py", line 6, in <module>
import pandas as pd
File "/Users/anentropic/.virtualenvs/anentropic/lib/python2.7/site-packages/pandas/__init__.py", line 7, in <module>
from . import hashtable, tslib, lib
File "pandas/tslib.pyx", line 614, in init pandas.tslib (pandas/tslib.c:81486)
File "pandas/tslib.pyx", line 573, in pandas.tslib.NaTType.__new__ (pandas/tslib.c:12539)
TypeError: __new__() takes exactly one argument (4 given)
I'm using django.
I have some tests that I'm trying to freeze time for, but when I decorate the test method, it is no longer found by django's test framework. Same deal when I decorate the class.
$ ./manage.py test app.TestClassName
Traceback (most recent call last):
...
ValueError: Test label 'app.TestClassName' does not refer to a test.
Without the decoration, the test is found (but fails, obviously).
I can freeze in .setUp()
and thaw in .tearDown()
, but the decorator syntax is nicer.
I think this is more App Engine's fault, but freezegun definitely doesn't work with App Engine.
I'm not sure how this could fit into the project, so feel free to resolve as "wont-fix", but here's a patch I put in my testing set up that makes freezegun work. I run it as part of my test case's setUp()
.
from freezegun import api
from google.appengine.api import datastore_types
from google.appengine.ext import db, ndb
import pytz
# datetime.utcnow() needs to stay naive.
if not hasattr(api.FakeDatetime, '_old_utcnow'):
@classmethod
def naive_utcnow(cls):
return cls._old_utcnow().replace(tzinfo=None)
api.FakeDatetime._old_utcnow = api.FakeDatetime.utcnow
api.FakeDatetime.utcnow = naive_utcnow
# ext.db.DateProperty.now() should return a FakeDate.
@staticmethod
def today():
return api.date_to_fakedate(api.real_datetime.now().date())
db.DateProperty.now = today
# ext.ndb.DatetimeProperty.now() should return a naive FakeDatetime.
def now(self):
now = datetime.utcnow()
if now.tzinfo:
now = now.astimezone(pytz.utc).replace(tzinfo=None)
return api.datetime_to_fakedatetime(now)
ndb.DateTimeProperty._now = now
# Validating FakeDatetime's should work as expected.
def validate_fakedatetime(name, value):
return api.datetime_to_fakedatetime(value)
# De-serializing a FakeDatetime should be the same as a regular datetime.
def load_datetime(value):
loaded_value = datastore_types._When(value)
if issubclass(datetime, api.FakeDatetime):
loaded_value = api.datetime_to_fakedatetime(loaded_value)
return loaded_value
# Tell App Engine how to handle FakeDatetime objects.
datastore_types._VALIDATE_PROPERTY_VALUES[api.FakeDatetime] = validate_fakedatetime
datastore_types._PACK_PROPERTY_VALUES[api.FakeDatetime] = datastore_types.PackDatetime
datastore_types._PROPERTY_MEANINGS[api.FakeDatetime] = datastore_types.entity_pb.Property.GD_WHEN
datastore_types._PROPERTY_CONVERSIONS[datastore_types.entity_pb.Property.GD_WHEN] = load_datetime
Sorry for the lousy Issue title, I don't know how to frase it, but the test case is pretty clear.
Test Case: https://gist.github.com/PuercoPop/4724228
# -*- coding: utf-8 -*-
from datetime import datetime
from freezegun import freeze_time
class A(object):
def __init__(self):
self.date = datetime.now()
def test_():
with freeze_time("1990-01-01 18:00:00"):
a = A()
assert a.date.year == 1990
It is difficult to provide an exact repro for this bug, but because this issue has been seen before, I hope the owner can determine the cause and the fix.
We have Django 1.5, and many of our test cases are failing with a stack-trace similar to the following:
Traceback (most recent call last):
File "/home/someuser/someproject/src/some_project/xyz/pqr/views.py", line 236, in test_one_type
't_type': t_types.DEP}
File "/home/someuser/someproject/src/some_project/test/urlcoverage.py", line 47, in get
return super(TestUrlCoverageMixin, self).get(url, _args, *_kwargs)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/test/client.py", line 453, in get
response = super(Client, self).get(path, data=data, **extra)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/test/client.py", line 279, in get
return self.request(**r)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/test/client.py", line 424, in request
six.reraise(*exc_info)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in get_response
response = middleware_method(request, response)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/contrib/sessions/middleware.py", line 38, in process_response
request.session.save()
File "/home/someuser/someproject/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py", line 51, in save
session_data=self.encode(self._get_session(no_load=must_create)),
File "/home/someuser/someproject/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 84, in encode
serialized = self.serializer().dumps(session_dict)
File "/home/someuser/someproject/lib/python2.7/site-packages/django/contrib/sessions/serializers.py", line 14, in dumps
return pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
PicklingError: Can't pickle <type 'datetime.datetime'>: it's not the same object as datetime.datetime
The test-case itself derives from a class in which freezegun calls appear. That class is something like:
class DateMockerTestCase(TestCase):
def setUp(self, _args, *_kwargs):
self._freezer = freeze_time("2011-05-10 12:00:00")
self._freezer.start()
# Ensure it's working.
assert datetime.datetime.now() == datetime.datetime(
2011, 05, 10, 12, 00, 00)
super(DateMockerTestCase, self).setUp(*args, **kwargs)
def tearDown(self, *args, **kwargs):
super(DateMockerTestCase, self).tearDown(*args, **kwargs)
self._freezer.stop()
As you can see, that's a typical use of freezegun package.
The issue exists in at least two commit places:
(1) 8ed7826 (master branch)
(2) freezegun version 0.1.11
Lastly, the issue does not exist if you checkout the commit ID mentioned in (1), but switch instead to the 'ctypes' branch.
Hope this gives people enough detail to figure out and fix the issue.
Importing freezegun before importing pandas causes the import of pandas to fail. If I test a bunch of modules with nose, then my tests importing pandas will all fail if they are run following a test that imports freezegun. Here's all you have to do recreate:
>>> import freezegun
>>> import pandas
vendor/python/lib/python2.7/site-packages/pandas/__init__.py:6: RuntimeWarning: datetime.datetime size changed, may indicate binary incompatibility
from . import hashtable, tslib, lib
vendor/python/lib/python2.7/site-packages/pandas/__init__.py:6: RuntimeWarning: datetime.date size changed, may indicate binary incompatibility
from . import hashtable, tslib, lib
__new__() takes exactly one argument (4 given)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "vendor/python/lib/python2.7/site-packages/pandas/__init__.py", line 6, in <module>
from . import hashtable, tslib, lib
File "tslib.pyx", line 313, in init pandas.tslib (pandas/tslib.c:38938)
File "tslib.pyx", line 290, in pandas.tslib.NaTType.__new__ (pandas/tslib.c:6135)
TypeError: __new__() takes exactly one argument (4 given)
It looks like freezegun whacks datetime.date and friends as soon as you import it, rather than wait until you use a decorator like @freezegun.freeze_time and then set things right again later. This makes it play very not-nice with other unit tests.
used pip install to get 0.0.8 - that version fails when running unittests using PyCharms unittest runner due to a bug in the sub method.
Looks like that is already fixed in git - so the question is - do you have plans to spin another package build so we can simply install it...
BTW - this is a totally awesome package - simple but really really useful.
Thanks!
As title says, it appears the FakeDatetime.date method (see the docs) is not implemented, and so inherits from the native date object. This leads to errors like TypeError: can't compare FakeDatetime to datetime.date
.
Testcase:
from unittest import TestCase
from datetime import datetime
@freeze_time(date(2015, 5, 1))
class TestDatetimeDateMethod(TestCase):
def test_method(self):
now = datetime.now()
print repr(now)
print repr(now.date())
Expected output:
FakeDatetime(2015, 5, 1, 0, 0)
FakeDate(2015, 5, 1)
Actual ouput:
FakeDatetime(2015, 5, 1, 0, 0)
datetime.date(2015, 5, 1)
Hi,
The release 0.1.18 seems to be available only on PyPI.
Thanks for developing freezegun!
This code fails
from freezegun import freeze_time
from datetime import datetime as dt
freezer = freeze_time('1980-01-01')
freezer.start()
assert dt.now() == dt(1980,1,1)
See #12 (comment)
Iโm not sure whose fault it is, but after the last six update, freezegun stopped working for me on Python 3.2/3 (2.7 works fine).
You can see it in this Travis build or on OS X in tox, I got https://gist.github.com/hynek/533346842083c6616d07
I solved it by pinning six to 1.4 for now.
Test that I am running:
class NotificationManagerTestCase(TestCase):
@freeze_time("2012-01-01 00:00:00", tz_offset=0)
def test_valid_manager_method(self):
user = UserFactory()
num_test_notifications = 5
for i in xrange(num_test_notifications):
NotificationFactory(user=user)
with freeze_time("2012-01-01 12:00:00", tz_offset=0):
import ipdb; ipdb.set_trace()
notifications = Notification.objects.filter(user=user).valid()
self.assertEqual(len(notifications), num_test_notifications)
Output:
Traceback (most recent call last):
File "/data/virtualenv/notifications/lib/python2.7/site-packages/freezegun/api.py", line 215, in wrapper
result = func(*args, **kwargs)
File "/vagrant/src/notifications/notifications/notification_data/tests/manager_tests.py", line 23, in test_valid_manager_method
import ipdb; ipdb.set_trace()
File "/data/virtualenv/notifications/lib/python2.7/site-packages/ipdb/__init__.py", line 16, in <module>
from ipdb.__main__ import set_trace, post_mortem, pm, run, runcall, runeval, launch_ipdb_on_exception
File "/data/virtualenv/notifications/lib/python2.7/site-packages/ipdb/__main__.py", line 51, in <module>
ipshell = InteractiveShellEmbed()
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/terminal/embed.py", line 97, in __init__
display_banner=display_banner
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/terminal/interactiveshell.py", line 320, in __init__
**kwargs
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 456, in __init__
self.init_history()
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 1480, in init_history
self.history_manager = HistoryManager(shell=self, parent=self)
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/core/history.py", line 481, in __init__
self.new_session()
File "<string>", line 2, in new_session
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/core/history.py", line 65, in needs_sqlite
return f(self, *a, **kw)
File "/data/virtualenv/notifications/lib/python2.7/site-packages/IPython/core/history.py", line 499, in new_session
NULL, "") """, (datetime.datetime.now(),))
InterfaceError: Error binding parameter 0 - probably unsupported type.
If I use pdb
instead of ipdb
then everything works fine. Not sure if this is related to freezegun or something else, but using ipdb
inside of a frozen test seems like a reasonable use-case.
We noticed a lot of our tests started failing today. It appears that freezegun was just updated yesterday on Oct 22. Many of our tests were using the class decorator, and now we receive errors like the following:
TypeError: unbound method setUpClass() must be called with DjangoTestClassName instance as first argument (got nothing instead)
Not really sure how else to report this issue, but we put the function decorator on all of our tests and that seems to have fixed the issue. Let me know if you need more information
Excerpt from the docs:
"[โฆ] all calls to datetime.datetime.now()
, datetime.datetime.utcnow()
, [โฆ] will return the time that has been frozen."
But this is not the behaviour I expect.
Example code:
from datetime import datetime
def test_something():
print('now(): ', datetime.now())
print('utcnow():', datetime.utcnow())
Output without Freezegun (system timezone is "Europe/Berlin"):
now(): 2015-03-10 00:46:40.465879
utcnow(): 2015-03-09 23:46:40.466031
Output with Freezegun (method decorated with @freeze_time('2012-03-11 19:21:23')
):
now(): 2012-03-11 19:21:23
utcnow(): 2012-03-11 19:21:23
However, I expected the output with Freezegun to reflect the offset (one hour, in this case) and, thus, to return two different date/time instances.
Hi there, I'm having a problem with getting py.test and freezegun to play well together. I'm not sure which of the two is to blame or whether I'm doing something wrong here, but I was hoping you might be able to shed some light on this.
All of this is using freezegun 0.1.18 from PyPi and py.test 2.6.1.
The simplest test works fine:
# test_discovery.py
class TestDiscovery(object):
def test(self):
assert True
> py.test test_discovery.py
========================== test session starts ==========================
platform darwin -- Python 2.7.5 -- py-1.4.23 -- pytest-2.6.1
collected 1 items
test_discovery.py .
The test is found and run, all great. But when I add freezegun, the test is no longer being found:
from freezegun import freeze_time
@freeze_time("2014-08-05")
class TestDiscovery(object):
def test(self):
assert True
> py.test test_discovery.py
========================== test session starts ==========================
platform darwin -- Python 2.7.5 -- py-1.4.23 -- pytest-2.6.1
collected 0 items
I'm running into similar (but possibly unrelated) issues when I want to freeze time on a function that uses a py.test fixture (this test works fine if I leave out freezegun):
import pytest
from freezegun import freeze_time
@pytest.fixture
def fixture():
return 42
@freeze_time("2014-08-05")
def test(fixture):
assert fixture == 42
> py.test test_discovery.py
========================== test session starts ==========================
platform darwin -- Python 2.7.5 -- py-1.4.23 -- pytest-2.6.1
collected 1 items
test_discovery.py F
=============================== FAILURES ================================
_________________________________ test __________________________________
args = (), kwargs = {}
def wrapper(*args, **kwargs):
with self:
> result = func(*args, **kwargs)
E TypeError: test() takes exactly 1 argument (0 given)
venv/lib/python2.7/site-packages/freezegun/api.py:219: TypeError
Any hints or ideas are much appreciated! Thanks.
Hi,
The latest release on pypi doesn't have a matching git tag.
The code to reproduce it is:
from unittest import TestCase
from moto import mock_s3
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from freezegun import freeze_time
class PoCTest(TestCase):
@mock_s3
def test_mixed_dates(self):
conn = S3Connection()
bucket = conn.create_bucket('foo')
with freeze_time("2014-07-30T01:00:00Z"):
k = Key(bucket)
k.key = 'bar'
k.set_contents_from_string('spam')
And the output when running it:
======================================================================
ERROR: test_mixed_dates (public.tests.test_poc.PoCTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/moto/core/models.py", line 61, in wrapper
result = func(*args, **kwargs)
File "/home/ubuntu/cloud-status/public/tests/test_poc.py", line 19, in test_mixed_dates
k.set_contents_from_string('spam')
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/s3/key.py", line 1305, in set_contents_from_string
encrypt_key=encrypt_key)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/s3/key.py", line 1172, in set_contents_from_file
chunked_transfer=chunked_transfer, size=size)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/s3/key.py", line 710, in send_file
chunked_transfer=chunked_transfer, size=size)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/s3/key.py", line 882, in _send_file_internal
query_args=query_args)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/s3/connection.py", line 544, in make_request
override_num_retries=override_num_retries)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/connection.py", line 939, in make_request
return self._mexe(http_request, sender, override_num_retries)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/connection.py", line 835, in _mexe
boto.log.debug('Token: %s' % self.provider.security_token)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/provider.py", line 210, in get_security_token
if self._credentials_need_refresh():
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/boto/provider.py", line 225, in _credentials_need_refresh
delta = self._credential_expiry_time - datetime.utcnow()
TypeError: can't subtract offset-naive and offset-aware datetimes
The strange thing is that this PoC runs on my workstation but fails at CircleCI. I'm almost sure that it is because of a different setting in timezone/date format/etc. Anyways, it crashes.
Hi Steve,
Noticed that as soon as you import freeze_time then calls to datetime.now() or date.today() will be return instances of FakeDatetime or FakeDate without a decorator of context manager (or raw start/stop) being invoked.
I.e. these tests (revised from your tests) should both pass (if I understand correctly):
import datetime
from freezegun import freeze_time
from freezegun.api import FakeDate, FakeDatetime
@freeze_time("Jan 14th, 2012")
def test_isinstance_with_active():
now = datetime.datetime.now()
assert isinstance(now, datetime.datetime)
assert isinstance(now, datetime.date)
assert isinstance(now, FakeDatetime)
today = datetime.date.today()
assert isinstance(today, datetime.date)
assert isinstance(today, FakeDate)
def test_isinstance_without_active():
now = datetime.datetime.now()
assert isinstance(now, datetime.datetime)
assert isinstance(now, datetime.date)
assert not isinstance(now, FakeDatetime)
today = datetime.date.today()
assert isinstance(today, datetime.date)
assert not isinstance(now, FakeDate)
However, test_isinstance_without_active
fails because now and today are Fake.
Eg:
from datetime import datetime
import pytz
from freezegun import freeze_time
d = datetime(2014, 10, 14, 7, tzinfo=pytz.timezone('America/Chicago'))
with freeze_time(d):
print datetime.utcnow()
Output:
2014-10-08 01:09:00
Expected output:
2014-10-08 12:00:00
Error
Traceback (most recent call last):
File "/home/dmwyatt/.virtualenvs/TestFreezegun/lib/python3.3/site-packages/freezegun/api.py", line 142, in tearDown
self._freezer.stop()
File "/home/dmwyatt/.virtualenvs/TestFreezegun/lib/python3.3/site-packages/freezegun/api.py", line 204, in stop
if hasattr(module, 'datetime') and module.datetime == FakeDatetime:
File "/home/dmwyatt/.virtualenvs/TestFreezegun/lib/python3.3/site-packages/django/utils/six.py", line 116, in __getattr__
_module = self._resolve()
File "/home/dmwyatt/.virtualenvs/TestFreezegun/lib/python3.3/site-packages/django/utils/six.py", line 105, in _resolve
return _import_module(self.mod)
File "/home/dmwyatt/.virtualenvs/TestFreezegun/lib/python3.3/site-packages/django/utils/six.py", line 76, in _import_module
__import__(name)
ImportError: No module named 'winreg'
I get this error when I decorate a django 1.6 unit test on Python 3.3 + Ubuntu.
The comments in six.py
method __getattr__
specifically mention 'winreg', but I don't have time to figure out exactly what is going on here right now.
It would be very pleasant if the PyPI release could include a wheel as well as the source distribution, which would make pip install freezegun
a little faster.
What do you think of having freeze_time
accept a timezone argument:
@freeze_time('2015-03-09 09:00:00', timezone='US/Pacific')
That would require adding pytz to the requirements, which should be fine since most Python projects have it.
Thoughts? I might develop it.
Not sure what is causing this, but all of our tests are breaking with the following error. Please let me know if there is any other help I can give. I'm assuming this is related to the recent upgrade to 2.3
Traceback (most recent call last):
File "build/bdist.linux-x86_64/egg/freezegun/api.py", line 302, in wrapper
with self:
File "build/bdist.linux-x86_64/egg/freezegun/api.py", line 218, in __enter__
self.start()
File "build/bdist.linux-x86_64/egg/freezegun/api.py", line 246, in start
attribute_value = getattr(module, module_attribute)
File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/celery/five.py", line 315, in __getattr__
return ModuleType.__getattribute__(self, name)
AttributeError: 'execute' object has no attribute '__file__'
A date should not be an instance of datetime.datetime:
$ python
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import freezegun
>>> f = freezegun.freeze_time('2001-01-01')
>>> f.start()
>>> import datetime
>>> isinstance(datetime.date.today(), datetime.datetime)
True
>>> f.stop()
>>> isinstance(datetime.date.today(), datetime.datetime)
False
>>>
Hey, not quite sure what's going on here, but my pip install
is failing on Travis on this package:
Collecting python-dateutil<2.0,>=1.0,>=2.1 (from freezegun==0.1.18->-r measurement_collector/downloaders/ea_rivers_and_sea_levels/requirements.txt (line 3))
Could not find a version that satisfies the requirement python-dateutil<2.0,>=1.0,>=2.1 (from freezegun==0.1.18->-r measurement_collector/downloaders/ea_rivers_and_sea_levels/requirements.txt (line 3)) (from versions: 1.4, 1.4.1, 1.5, 2.1, 2.2, 2.3, 2.4.0)
Some externally hosted files were ignored as access to them may be unreliable (use --allow-external to allow).
No distributions matching the version for python-dateutil<2.0,>=1.0,>=2.1 (from freezegun==0.1.18->-r measurement_collector/downloaders/ea_rivers_and_sea_levels/requirements.txt (line 3))
The full output is here:
https://travis-ci.org/sealevelresearch/tide-gauge-measurement-collector/jobs/49623921#L122
Curiously if I just do pip install 'python-dateutil<2.0,>=1.0,>=2.1'
on my machine it successfully installs python-dateutil 2.4.0 (Python 3.2.3, pip 1.5.6). Is this a problem with a newer python / pip?
Is the dependency specification 'python-dateutil<2.0,>=1.0,>=2.1'
AND or OR? I don't really know what's happening here :)
When scanning for modules to replace, ==
is used to identify datetime in modules.
This causes problems for objects that has overriden __eq__
to always return True - this happens with mock.ANY
:
https://code.google.com/p/mock/source/browse/mock.py?spec=svnd356250e275daa62b2972521885f42fa639341e6&r=e7c5f97dc1b486fbf2e7fb111ec3e6675f9d3418#1954
If ANY is imported in a module, it will simply be replaced with datetime.datetime
, which is not really expected.
When installing freezegun
with pip install freezegun
, there seems to be a side effect, which is that it installs its tests into site-packages as well.
This can have a negative effect for tests in a tests/
directory that need to import from other modules under said directory.
I assert that packages=find_packages(),
in setup.py should change to:
provides=[
'freezegun',
],
packages=[i for i in find_packages() if i.startswith('freezegun')],
Apparently pytest puts a module into sys.modules with a None
key, this causes this code:
Line 199 in aa72636
None.startswith()
doesn't work.
Probably this should have a check above it looking for if mod_name is None: continue
as well.
It would be very cool if a warning was printed (or even an error was raised) when the patching can't be performed properly, e.g.. because of a wrong import order.
Alternatively something like freezegun.assert_can_patch() would be handy, raising an error when datetime was imported before and can't be patched properly.
Dateutil library won't support operations with the mock datetime objects:
In [1]: from freezegun import freeze_time
In [2]: import datetime
In [3]: import dateutil
In [4]: freezer = freeze_time("2012-12-12")
In [5]: freezer.start()
In [6]: datetime.datetime.now() + dateutil.relativedelta.relativedelta(days=1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/vagrant/<ipython console> in <module>()
/home/vagrant/.virtualenvs/upshot/local/lib/python2.7/site-packages/dateutil/relativedelta.pyc in __radd__(self, other)
245 def __radd__(self, other):
246 if not isinstance(other, datetime.date):
--> 247 raise TypeError, "unsupported type for add operation"
248 elif self._has_time and not isinstance(other, datetime.datetime):
249 other = datetime.datetime.fromordinal(other.toordinal())
TypeError: unsupported type for add operation
See #93
Here is a test I ran from the shell to demonstrate:
with freeze_time('3000-1-1'):
from django.utils.timezone import now
print now()
The result was:
2013-01-29 20:38:49.097124+00:00
Tests fail with
ImportError: cannot import name 'utils'
So I get this:
___________________ TestNotifications.test_conference_start ____________________ tests_python/api/test_notifications.py:20: in test_conference_start freez.start() env/lib/python3.4/site-packages/freezegun/api.py:250: in start if attribute_value == real_datetime: env/lib/python3.4/site-packages/sqlalchemy/orm/path_registry.py:54: in __eq__ self.path == other.path E AttributeError: type object 'datetime.datetime' has no attribute 'path'
Out of this code:
freez = freeze_time("2017-01-14 12:00:00") freez.start()
This worked in 0.2.2.
I'm trying to use Freezegun in my Django tests, but it fails when pickling/saving sessions, just like in issue #3.
Apparently that is resolved, and it does indeed work in my Python console. In my Django tests, however, it fails. Acording to the warning in the documentation, I should import freezegun right from the beginning, but when would that be in Django's case? I've tried to import it at the beginning of manage.py, as well as in my settings.py file.
The error that I get when importing in manage.py or settings.py is:
Traceback (most recent call last):
File "/path/to/project/panel/tests.py", line 44,
in setUp
self.add_customer_category()
File "/path/to/project/panel/tests.py", line 62,
in add_customer_category
response = self.c.get('/panel/customers/categories/')
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/test/client.py", line 439, in get
response = super(Client, self).get(path, data=data, **extra)
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/test/client.py", line 244, in get
return self.request(**r)
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/path/to/project/panel/views/customers.py"
, line 310, in customer_categories
}, context_instance=RequestContext(request))
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/template/context.py", line 176, in __init__
self.update(processor(request))
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/core/context_processors.py", line 54, in tz
return {'TIME_ZONE': timezone.get_current_timezone_name()}
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/utils/timezone.py", line 136, in get_current_timezone_name
return _get_timezone_name(get_current_timezone())
File "/path/to/env/local/lib/python2.7/site-pack
ages/django/utils/timezone.py", line 147, in _get_timezone_name
local_now = datetime.now(timezone)
TypeError: now() takes exactly 1 argument (2 given)
Has anyone else successfully used freezegun with Django? If so, how?
Thanks,
Olav.
i ran into an issue with six.moves
and freezegun
, which may or may not have been due to bad versions. in particular, though, the fix in my case was to pass ignore=['six.moves']
to freezegun.freeze_time
-- note the lack of trailing .
from the default ignore in the library.
any reason why you only ignore six.moves.*
and not six.moves
itself?
Hi,
I've been using freezegun to test code which supports both Python 2 and 3, and found that freezegun appears to result in different time values being returned by datetime.now(timezone)
under different Python versions.
I've cut this down into a gist: https://gist.github.com/PeterJCLaw/96a68c04d0772ccb1182, which contains both the code and the outputs I'm seeing. Those outputs are from version 0.3.1, but I believe I've confirmed that the behaviour is the same using the current master branch as well.
I think based on what's there that it's the Python 3 behaviour which is wrong, but I'm not sure which is expected.
Is this behaving as you'd expect?
Thanks,
Peter
Here: https://travis-ci.org/getnikola/invariant-builds/jobs/20892082#L744
Note that, with a different way of running my stuff, it works just fine: https://travis-ci.org/getnikola/invariant-builds/jobs/20888909#L742
Another test suite also uses freezegun, yet it works here. This is an ultra-weird heisenbug.
Does freezegun support Python 3?
If so, it would be nice to designate that on PyPI using classifiers in setup.py (see https://pypi.python.org/pypi?%3Aaction=list_classifiers)
If not, what does the path forward look like?
When writing a unittest TestCase with @freeze_time, datetime.now() inside the setUp method returns the current time instead of the frozen time. Also affects tearDown.
@freeze_time('2014-03-15 12:00 pm')
class TestSetupTime(unittest.TestCase):
def setUp(self):
print 'setup', datetime.now()
def tearDown(self):
print 'teardown', datetime.now()
def test_time(self):
print 'test', datetime.now()
setup 2014-09-30 17:21:52.945426
test 2014-03-15 12:00:00
teardown 2014-09-30 17:21:53.152456
Module A gets imported inside freeze_time
context manager
Module A imports datetime.datetime
(patched with freezegun).
Context manager exists and unpatches all modules it has tracked in undo_changes
.
The problem is that module A still has FakeDatetime
instead of datetime.datetime
,
which results in something like that if it gets called:
return cls.times_to_freeze[-1]
IndexError: list index out of range
Sorry, I have no test to show this bug.
The faked time.time() does not support sub second granularity. Probably because it uses time.mktime() to produce the result? Would be nice with a behaviour that reflects that of the real time.time() function.
Hi, thanks for your work, it's very helpful.
I tried to update version from 0.1.18 to 0.1.19 but I got into an apparently different behaviour when freezegun is used as a test case class decorator. This is my test case:
@freeze_time(timezone.now())
class AfterSignupTestCase(BaseSignupTestCase):
def setUp(self):
super(AfterSignupTestCase, self).setUp()
mail_patcher = patch('timeline.tasks.mailgun.add_list_member')
test_timeline_patcher = patch('timeline.models.User.create_test_timeline')
with mail_patcher as self.mailgun_mock, test_timeline_patcher as self.create_test_timeline_mock:
self.signup_resp = self.client.post(self.endpoint, data=self.valid_data)
self.assertEqual(status.HTTP_201_CREATED, self.signup_resp.status_code)
self.new_user = User.objects.get(pk=self.signup_resp.data['id'])
def test_new_user_has_correct_sign_up_date(self):
self.assertEqual(timezone.now().replace(microsecond=0), self.new_user.registered_on.replace(microsecond=0))
The test on the dates always fails with version 0.1.19, while it's fine on 0.1.18. It fails because of a difference in seconds.
Has anything changed in the expected usage, or is it a bug?
Thanks!
The new version of freezegun replaces an imported mock.call with datetime.datetime when trying to cleanup the patching.
This occurs because mock's call class compares defines eq in a was that compares equal to FakeDatetime.
Here's a snippet of code that reproduces the problem, using mock==1.0.1:
(network-reporting-env3) [2174-cleanup-requirements-txt]$ pip install freezegun==0.2.5
Downloading/unpacking freezegun==0.2.5
Downloading freezegun-0.2.5.tar.gz
Running setup.py egg_info for package freezegun
Requirement already satisfied (use --upgrade to upgrade): six in /Users/jboggs/Mopub/network-reporting-env3/lib/python2.7/site-packages (from freezegun==0.2.5)
Requirement already satisfied (use --upgrade to upgrade): python-dateutil>=1.0,!=2.0 in /Users/jboggs/Mopub/network-reporting-env3/lib/python2.7/site-packages (from freezegun==0.2.5)
Installing collected packages: freezegun
Found existing installation: freezegun 0.2.2
Uninstalling freezegun:
Successfully uninstalled freezegun
Running setup.py install for freezegun
Successfully installed freezegun
Cleaning up...
(network-reporting-env3) [2174-cleanup-requirements-txt]$
(network-reporting-env3) [2174-cleanup-requirements-txt]$
(network-reporting-env3) [2174-cleanup-requirements-txt]$ python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from freezegun import freeze_time
>>> from mock import call
>>> with freeze_time('2000-01-01'):
... pass
...
>>> call
<type 'datetime.datetime'>
Not really freezegun's fault... maybe mock.call shouldn't be equal to all sorts of things. But, might be worth doing the comparisons in stop() some other way
When decorating a class with a frozen time, if a method calls out to another method on the class, it will cause the patcher to stop and undo the frozen time for the rest of the initial calling method. This appears to only happen when from datetime import datetime
is called as opposed to import datetime
.
For example:
from datetime import datetime
from freezegun import freeze_time
import unittest
@freeze_time('1980-01-01')
class FooTest(object):
def test_bar(self):
datetime.now() # returns 1980-01-01 00:00:00
self.other_func()
datetime.now() # returns 2015-04-21 07:03:00
def other_func(self):
# do stuff
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.