Skip to content

Commit

Permalink
Merge branch 'release/1.3.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmalloc committed Dec 17, 2018
2 parents fbd09d6 + ca556ee commit c4baad0
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -4,4 +4,4 @@
build
.tox
dist
.env
.eggs
13 changes: 5 additions & 8 deletions .travis.yml
@@ -1,16 +1,13 @@
language: python
sudo: false
dist: xenial
python:
- 2.6
- 2.7
- 3.3
- 3.4
- 3.5
- pypy
- 3.6
- 3.7
install:
- pip install -e .
- python scripts/test_setup.py
script: py.test tests
- pip install -e .[testing]
script: pytest tests
deploy:
provider: pypi
user: vmalloc
Expand Down
4 changes: 3 additions & 1 deletion flux/__version__.py
@@ -1 +1,3 @@
__version__ = "1.3.4"
import pkg_resources

__version__ = pkg_resources.get_distribution('flux').version
4 changes: 4 additions & 0 deletions flux/current_timeline.py
Expand Up @@ -23,10 +23,14 @@ def _wrapper(*args, **kwargs):
class datetime(_datetime.datetime):
@classmethod
def now(cls):
if not _current.is_modified():
return _datetime.datetime.now()
return _datetime.datetime.fromtimestamp(time())

@classmethod
def utcnow(cls):
if not _current.is_modified():
return _datetime.datetime.utcnow()
return _datetime.datetime.utcfromtimestamp(time())

class date(_datetime.date):
Expand Down
24 changes: 18 additions & 6 deletions flux/timeline.py
Expand Up @@ -11,12 +11,16 @@ class Timeline(object):
def __init__(self, start_time=None):
super(Timeline, self).__init__()
current_time = self._real_time()
if start_time is None:
start_time = current_time
self._forced_time = None
self._scheduled = []
self._time_factor = 1
self._time_correction = TimeCorrection(start_time, current_time)
self._time_correction = None

if start_time is not None:
self._correct_time(base=start_time)

def is_modified(self):
return self._time_correction is not None

def _real_sleep(self, seconds):
time.sleep(seconds)
Expand Down Expand Up @@ -47,7 +51,13 @@ def freeze(self):
"""
self.set_time_factor(0)

def _correct_time(self):
def _correct_time(self, base=None):
current_time = self._real_time()
if base is None:
base = current_time
if self._time_correction is None:
self._time_correction = TimeCorrection(base, current_time)

self._time_correction.virtual_time = self.time()
self._time_correction.real_time = self._real_time()
# shift stems from the previous correction...
Expand Down Expand Up @@ -106,8 +116,10 @@ def time(self):
"""
if self._forced_time is not None:
return self._forced_time
current_time = self._real_time()
return self._time_correction.virtual_time + self._time_correction.shift + (current_time - self._time_correction.real_time) * self._time_factor
returned = self._real_time()
if self._time_correction is not None:
returned = self._time_correction.virtual_time + self._time_correction.shift + (returned - self._time_correction.real_time) * self._time_factor
return returned

@contextlib.contextmanager
def _get_forced_time_context(self, time):
Expand Down
21 changes: 21 additions & 0 deletions setup.cfg
@@ -0,0 +1,21 @@
[metadata]
name = flux
classifiers =
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
summary = Artificial time library
description-file =
README.md
description-content-type = text/markdown
license = BSD
author = Rotem Yaari
author_email = vmalloc@gmail.com
url = https://github.com/getslash/flux


[extras]
testing =
pyforge
pytest
gevent
31 changes: 7 additions & 24 deletions setup.py
@@ -1,25 +1,8 @@
import os
from setuptools import setup, find_packages
#!/usr/bin/env python
from setuptools import setup

with open(os.path.join(os.path.dirname(__file__), "flux", "__version__.py")) as version_file:
exec(version_file.read()) # pylint: disable=W0122

setup(name="flux",
description="Artificial time library",
license="BSD",
author="Rotem Yaari",
author_email="vmalloc@gmail.com",
classifiers=[
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
],

version=__version__, # pylint: disable=E0602
packages=find_packages(exclude=["tests"]),
install_requires=[],
scripts=[],
namespace_packages=[]
)
setup(
setup_requires=['pbr>=3.0', 'setuptools>=17.1'],
pbr=True,
long_description_content_type='text/markdown; charset=UTF-8',
)
36 changes: 36 additions & 0 deletions tests/conftest.py
@@ -0,0 +1,36 @@
import time
from forge import Forge
import pytest


@pytest.fixture
def forge(request):

returned = Forge()

@request.addfinalizer
def cleanup(): # pylint: disable=unused-variable
returned.verify()
returned.restore_all_replacements()

return returned


@pytest.fixture
def mocked_time_module():

class _Mocked(object):

def __init__(self):
self._time = time.time()

def time(self):
return self._time

def __set_time__(self, value):
self._time = value

def __advance__(self, increment=30):
self._time += increment

return _Mocked()
2 changes: 1 addition & 1 deletion tests/test__readme_doctest.py
Expand Up @@ -13,4 +13,4 @@ def test__readme_doctests(self):
readme_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "README.md"))
self.assertTrue(os.path.exists(readme_path))
result = doctest.testfile(readme_path, module_relative=False, globs=dict(time=_FakeTimeModule()))
self.assertEquals(result.failed, 0, "%s tests failed!" % result.failed)
self.assertEqual(result.failed, 0, "%s tests failed!" % result.failed)
48 changes: 24 additions & 24 deletions tests/test__timeline.py
Expand Up @@ -29,20 +29,20 @@ def _get_timeline(self):
class TimelineAPITest(TimelineTestBase):

def test__time_does_not_progress(self):
self.assertEquals(self.timeline.time(), self.timeline.time())
self.assertEqual(self.timeline.time(), self.timeline.time())

def test__sleep(self):
start_time = self.timeline.time()
sleep_time = 6.5
self.timeline.sleep(sleep_time)
self.assertEquals(self.timeline.time(), start_time + sleep_time)
self.assertEqual(self.timeline.time(), start_time + sleep_time)

def test__sleep_wait_all_scheduled(self):
start_time = self.timeline.time()
self.timeline.schedule_callback(100, setattr, self, "called1", True)
self.timeline.schedule_callback(200, setattr, self, "called2", True)
self.timeline.sleep_wait_all_scheduled()
self.assertEquals(self.timeline.time(), start_time + 200)
self.assertEqual(self.timeline.time(), start_time + 200)
self.assertTrue(self.called1)
self.assertTrue(self.called2)

Expand Down Expand Up @@ -121,8 +121,8 @@ def sleep(self, seconds):
def test__default_factor(self):
start_time = self.timeline.time()
self.sleep(10)
self.assertEquals(self.timeline.time(), start_time + 10)
self.assertEquals(self._real_time, self._start_real_time + 10)
self.assertEqual(self.timeline.time(), start_time + 10)
self.assertEqual(self._real_time, self._start_real_time + 10)

def test__scheduled_callbacks(self):
start_time = self.timeline.time()
Expand All @@ -132,8 +132,8 @@ def test__scheduled_callbacks(self):
self.sleep(10)
# need to trigger the callbacks
self.timeline.sleep(0)
self.assertEquals(self.timeline.time(), start_time + 10)
self.assertEquals(self._callback_calls, [schedule_time])
self.assertEqual(self.timeline.time(), start_time + 10)
self.assertEqual(self._callback_calls, [schedule_time])

def test__factor_changes_real_sleeps(self):
self._test__factor_changes(real_sleep=True)
Expand All @@ -143,7 +143,7 @@ def test__factor_changes_fake_sleeps(self):

def test__freeze(self):
self.timeline.freeze()
self.assertEquals(self.timeline.get_time_factor(), 0)
self.assertEqual(self.timeline.get_time_factor(), 0)

def _test__factor_changes(self, real_sleep):
expected_virtual_time = self.timeline.time()
Expand All @@ -157,7 +157,7 @@ def _test__factor_changes(self, real_sleep):
vtime_before_factor_change = self.timeline.time()
self.timeline.set_time_factor(factor)
vtime_after_factor_change = self.timeline.time()
self.assertEquals(
self.assertEqual(
vtime_before_factor_change, vtime_after_factor_change,
"set_time_factor() unexpectedly changed virtual time!")
if real_sleep:
Expand Down Expand Up @@ -193,8 +193,8 @@ def callback(self):
self.called_time = self.timeline.time()

def tearDown(self):
self.assertEquals(self.called_count, 1)
self.assertEquals(self.called_time, self.start_time + self.sleep_time)
self.assertEqual(self.called_count, 1)
self.assertEqual(self.called_time, self.start_time + self.sleep_time)
super(ScheduleTest, self).tearDown()

def test__one_sleep(self):
Expand All @@ -203,14 +203,14 @@ def test__one_sleep(self):
def test__several_sleeps(self):
for i in range(3):
self.timeline.sleep(self.sleep_time / 4)
self.assertEquals(self.called_count, 0)
self.assertEqual(self.called_count, 0)
self.timeline.sleep(self.sleep_time)

def test__advance_time(self):
dest_time = self.start_time + self.sleep_time * 10
self.timeline.set_time(dest_time)
self.assertEquals(self.timeline.time(), dest_time)
self.assertEquals(self.called_count, 0)
self.assertEqual(self.timeline.time(), dest_time)
self.assertEqual(self.called_count, 0)
self.timeline.sleep(0)


Expand Down Expand Up @@ -244,20 +244,20 @@ def tearDown(self):

def test__schedule_sequence(self):
for i in range(1, self.num_steps + 1):
self.assertEquals(self.value, i - 1)
self.assertEqual(self.value, i - 1)
self.timeline.sleep(i - 1)
self.assertEquals(self.value, i - 1)
self.assertEqual(self.value, i - 1)
self.timeline.sleep(1)
self.assertEquals(self.value, i)
self.assertEqual(self.value, i)

def test__schedule_sequence_and_interrupt(self):
for i in range(1, self.num_steps - 1):
self.timeline.sleep(i)
self.assertEquals(self.value, i)
self.assertEqual(self.value, i)
self.assertTrue(self.seq.is_running())
self.seq.stop()
self.timeline.sleep(i + 1)
self.assertEquals(self.value, i)
self.assertEqual(self.value, i)


class CurrentTimeLineTest(TestCase):
Expand All @@ -271,8 +271,8 @@ def test__current_timeline_replacing(self):
new_factor = 12345
flux.current_timeline.set(new_timeline)
flux.current_timeline.set_time_factor(new_factor)
self.assertEquals(flux.current_timeline.get_time_factor(), new_factor)
self.assertEquals(new_timeline.get_time_factor(), new_factor)
self.assertEqual(flux.current_timeline.get_time_factor(), new_factor)
self.assertEqual(new_timeline.get_time_factor(), new_factor)


class DatetimeTest(TimelineTestBase):
Expand All @@ -285,17 +285,17 @@ def setUp(self):
def test__datetime_now(self):
now = flux.current_timeline.datetime.now()
self.assertIsInstance(now, datetime.datetime)
self.assertEquals(now.timetuple(), datetime.datetime.fromtimestamp(
self.assertEqual(now.timetuple(), datetime.datetime.fromtimestamp(
flux.current_timeline.time()).timetuple())

def test__datetime_utcnow(self):
now = flux.current_timeline.datetime.utcnow()
timestamp = calendar.timegm(now.utctimetuple())
self.assertEquals(now.utctimetuple(),
self.assertEqual(now.utctimetuple(),
time.gmtime(flux.current_timeline.time()))

def test__datetime_date_today(self):
now = flux.current_timeline.datetime.now()
today = flux.current_timeline.date.today()
self.assertIsInstance(now, datetime.date)
self.assertEquals(now.date(), today)
self.assertEqual(now.date(), today)
19 changes: 19 additions & 0 deletions tests/test_time_drift.py
@@ -0,0 +1,19 @@
from flux import timeline
import pytest

def test_time_drift_default_factor(forge, mocked_time_module):
forge.replace_with(timeline, "time", mocked_time_module)
t = timeline.Timeline()
assert t.time() == mocked_time_module.time()
mocked_time_module.__advance__()
assert t.time() == mocked_time_module.time()

def test_time_drift_change_restore_default_factor(forge, mocked_time_module):
forge.replace_with(timeline, "time", mocked_time_module)
t = timeline.Timeline()
assert t.time() == mocked_time_module.time()
mocked_time_module.__advance__()
t.set_time_factor(1.5)
t.set_time_factor(1)
mocked_time_module.__advance__()
assert t.time() == mocked_time_module.time()
9 changes: 0 additions & 9 deletions tox.ini

This file was deleted.

0 comments on commit c4baad0

Please sign in to comment.