Hello community,

here is the log from the commit of package python-futurist for openSUSE:Factory 
checked in at 2016-03-07 13:28:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-futurist (Old)
 and      /work/SRC/openSUSE:Factory/.python-futurist.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-futurist"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-futurist/python-futurist.changes  
2016-01-11 19:12:18.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-futurist.new/python-futurist.changes     
2016-03-07 13:30:02.000000000 +0100
@@ -1,0 +2,19 @@
+Sun Feb 28 20:19:32 UTC 2016 - [email protected]
+
+- update to 0.13.0:
+  * Single quote the callables name (when submission errors
+  * Updated from global requirements
+  * Reschedule failed periodic tasks after a short delay
+  * Fix wrong comparison in reject_when_reached
+  * Updated from global requirements
+  * Ensure all futures have completed before run returns
+  * Allow PeriodicWorker to skip executor shutdown in case of a preexisting 
executor
+  * Expose underlying futures.CancelledError
+  * Updated from global requirements
+  * Modification of the example code
+  * PeriodicWorker.create to accept arguments for periodic tasks
+  * Handle exceptions from executor.submit in PeriodicWorker
+  * Add periodics.is_periodic to check if object is a periodic task
+  * py26/py33 are no longer supported by Infra's CI
+
+-------------------------------------------------------------------

Old:
----
  futurist-0.9.0.tar.gz

New:
----
  futurist-0.13.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-futurist.spec ++++++
--- /var/tmp/diff_new_pack.78Pn9P/_old  2016-03-07 13:30:03.000000000 +0100
+++ /var/tmp/diff_new_pack.78Pn9P/_new  2016-03-07 13:30:03.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python-futurist
-Version:        0.9.0
+Version:        0.13.0
 Release:        0
 Summary:        Useful additions to futures, from the future
 License:        Apache-2.0
@@ -29,7 +29,7 @@
 BuildRequires:  python-setuptools
 Requires:       python-contextlib2 >= 0.4.0
 Requires:       python-futures >= 3.0
-Requires:       python-monotonic >= 0.3
+Requires:       python-monotonic >= 0.6
 Requires:       python-six >= 1.9.0
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 %if 0%{?suse_version} && 0%{?suse_version} <= 1110

++++++ futurist-0.9.0.tar.gz -> futurist-0.13.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/AUTHORS new/futurist-0.13.0/AUTHORS
--- old/futurist-0.9.0/AUTHORS  2015-12-21 20:52:56.000000000 +0100
+++ new/futurist-0.13.0/AUTHORS 2016-02-23 15:49:16.000000000 +0100
@@ -4,4 +4,6 @@
 Joshua Harlow <[email protected]>
 Monty Taylor <[email protected]>
 Ronald Bradford <[email protected]>
+Surojit Pathak <[email protected]>
 THOMAS J. COCOZZELLO <[email protected]>
+janonymous <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/ChangeLog 
new/futurist-0.13.0/ChangeLog
--- old/futurist-0.9.0/ChangeLog        2015-12-21 20:52:56.000000000 +0100
+++ new/futurist-0.13.0/ChangeLog       2016-02-23 15:49:16.000000000 +0100
@@ -1,6 +1,38 @@
 CHANGES
 =======
 
+0.13.0
+------
+
+* Single quote the callables name (when submission errors
+* Updated from global requirements
+* Reschedule failed periodic tasks after a short delay
+* Fix wrong comparison in reject_when_reached
+
+0.12.0
+------
+
+* Updated from global requirements
+* Ensure all futures have completed before run returns
+
+0.11.0
+------
+
+* Updated from global requirements
+* Allow PeriodicWorker to skip executor shutdown in case of a preexisting 
executor
+
+0.10.0
+------
+
+* Expose underlying futures.CancelledError
+* Updated from global requirements
+* Updated from global requirements
+* Modification of the example code
+* PeriodicWorker.create to accept arguments for periodic tasks
+* Handle exceptions from executor.submit in PeriodicWorker
+* Add periodics.is_periodic to check if object is a periodic task
+* py26/py33 are no longer supported by Infra's CI
+
 0.9.0
 -----
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/PKG-INFO new/futurist-0.13.0/PKG-INFO
--- old/futurist-0.9.0/PKG-INFO 2015-12-21 20:52:56.000000000 +0100
+++ new/futurist-0.13.0/PKG-INFO        2016-02-23 15:49:16.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: futurist
-Version: 0.9.0
+Version: 0.13.0
 Summary: Useful additions to futures, from the future.
 Home-page: http://www.openstack.org/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/doc/source/examples.rst 
new/futurist-0.13.0/doc/source/examples.rst
--- old/futurist-0.9.0/doc/source/examples.rst  2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/doc/source/examples.rst 2016-02-23 15:48:56.000000000 
+0100
@@ -8,54 +8,72 @@
 
 .. testcode::
 
-    import time
+    # NOTE: enable printing timestamp for additional data
 
+    import sys
     import futurist
+    import eventlet
 
     def delayed_func():
-        time.sleep(0.1)
-        return "hello"
+        print("started")
+        eventlet.sleep(3)
+        print("done")
 
+    #print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
     e = futurist.SynchronousExecutor()
     fut = e.submit(delayed_func)
-    print(fut.result())
+    eventlet.sleep(1)
+    print("Hello")
+    eventlet.sleep(1)
     e.shutdown()
+    #print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
 
 **Expected output:**
 
 .. testoutput::
 
-    hello
-
+    started
+    done
+    Hello
 
-------------------------------------------
-Creating and using a thread-based executor
-------------------------------------------
+------------------------------------------------
+Creating and using a green thread-based executor
+------------------------------------------------
 
 .. testcode::
 
-    import time
+    # NOTE: enable printing timestamp for additional data
 
+    import sys
     import futurist
+    import eventlet
 
     def delayed_func():
-        time.sleep(0.1)
-        return "hello"
+        print("started")
+        eventlet.sleep(3)
+        print("done")
 
-    e = futurist.ThreadPoolExecutor()
+    #print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
+    e = futurist.GreenThreadPoolExecutor()
     fut = e.submit(delayed_func)
-    print(fut.result())
+    eventlet.sleep(1)
+    print("Hello")
+    eventlet.sleep(1)
     e.shutdown()
+    #print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
 
 **Expected output:**
 
 .. testoutput::
 
-    hello
+    started
+    Hello
+    done
 
-------------------------------------------------
-Creating and using a green thread-based executor
-------------------------------------------------
+
+------------------------------------------
+Creating and using a thread-based executor
+------------------------------------------
 
 .. testcode::
 
@@ -67,7 +85,7 @@
         time.sleep(0.1)
         return "hello"
 
-    e = futurist.GreenThreadPoolExecutor()
+    e = futurist.ThreadPoolExecutor()
     fut = e.submit(delayed_func)
     print(fut.result())
     e.shutdown()
@@ -78,7 +96,6 @@
 
     hello
 
-
 -------------------------------------------
 Creating and using a process-based executor
 -------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/__init__.py 
new/futurist-0.13.0/futurist/__init__.py
--- old/futurist-0.9.0/futurist/__init__.py     2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/futurist/__init__.py    2016-02-23 15:48:56.000000000 
+0100
@@ -19,6 +19,8 @@
 from futurist._futures import Future  # noqa
 from futurist._futures import GreenFuture  # noqa
 
+from futurist._futures import CancelledError  # noqa
+
 from futurist._futures import GreenThreadPoolExecutor  # noqa
 from futurist._futures import ProcessPoolExecutor  # noqa
 from futurist._futures import SynchronousExecutor  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/_futures.py 
new/futurist-0.13.0/futurist/_futures.py
--- old/futurist-0.9.0/futurist/_futures.py     2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/futurist/_futures.py    2016-02-23 15:48:56.000000000 
+0100
@@ -26,6 +26,9 @@
 from futurist import _utils
 
 
+CancelledError = _futures.CancelledError
+
+
 class RejectedSubmission(Exception):
     """Exception raised when a submitted call is rejected (for some reason)."""
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/_utils.py 
new/futurist-0.13.0/futurist/_utils.py
--- old/futurist-0.9.0/futurist/_utils.py       2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/futurist/_utils.py      2016-02-23 15:48:56.000000000 
+0100
@@ -17,6 +17,7 @@
 import inspect
 import multiprocessing
 import sys
+import threading
 import traceback
 
 from monotonic import monotonic as now  # noqa
@@ -116,3 +117,26 @@
         # just setup two threads since it's hard to know what else we
         # should do in this situation.
         return default
+
+
+class Barrier(object):
+    """A class that ensures active <= 0 occur before unblocking."""
+
+    def __init__(self, cond_cls=threading.Condition):
+        self._active = 0
+        self._cond = cond_cls()
+
+    def incr(self):
+        with self._cond:
+            self._active += 1
+            self._cond.notify_all()
+
+    def decr(self):
+        with self._cond:
+            self._active -= 1
+            self._cond.notify_all()
+
+    def wait(self):
+        with self._cond:
+            while self._active > 0:
+                self._cond.wait()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/periodics.py 
new/futurist-0.13.0/futurist/periodics.py
--- old/futurist-0.9.0/futurist/periodics.py    2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/futurist/periodics.py   2016-02-23 15:48:57.000000000 
+0100
@@ -115,6 +115,16 @@
     return missing_attrs
 
 
+def is_periodic(obj):
+    """Check whether an object is a valid periodic callable.
+
+    :param obj: object to inspect
+    :type obj: anything
+    :return: True if obj is a periodic task, otherwise False
+    """
+    return callable(obj) and not _check_attrs(obj)
+
+
 def periodic(spacing, run_immediately=False, enabled=True):
     """Tags a method/function as wanting/able to execute periodically.
 
@@ -284,6 +294,31 @@
     return immediates, schedule
 
 
+_SCHEDULE_RETRY_EXCEPTIONS = (RuntimeError, futurist.RejectedSubmission)
+
+
+class ExecutorFactory(object):
+    """Base class for any executor factory."""
+
+    shutdown = True
+    """Whether the executor should be shut down on periodic worker stop."""
+
+    def __call__(self):
+        """Return the executor to be used."""
+        raise NotImplementedError()
+
+
+class ExistingExecutor(ExecutorFactory):
+    """An executor factory returning the existing object."""
+
+    def __init__(self, executor, shutdown=False):
+        self._executor = executor
+        self.shutdown = shutdown
+
+    def __call__(self):
+        return self._executor
+
+
 class PeriodicWorker(object):
     """Calls a collection of callables periodically (sleeping as needed...).
 
@@ -306,6 +341,10 @@
         'successes': 0,
     }
 
+    # When scheduling fails temporary, use a random delay between 0.9-1.1 sec.
+    _RESCHEDULE_DELAY = 0.9
+    _RESCHEDULE_JITTER = 0.2
+
     DEFAULT_JITTER = fractions.Fraction(5, 100)
     """
     Default jitter percentage the built-in strategies (that have jitter
@@ -355,7 +394,7 @@
                log=None, executor_factory=None,
                cond_cls=threading.Condition, event_cls=threading.Event,
                schedule_strategy='last_started', now_func=utils.now,
-               on_failure=None):
+               on_failure=None, args=_NO_OP_ARGS, kwargs=_NO_OP_KWARGS):
         """Automatically creates a worker by analyzing object(s) methods.
 
         Only picks up methods that have been tagged/decorated with
@@ -377,7 +416,7 @@
                                  provided one will be created that uses
                                  the :py:class:`~futurist.SynchronousExecutor`
                                  class)
-        :type executor_factory: callable
+        :type executor_factory: ExecutorFactory or any callable
         :param cond_cls: callable object that can
                           produce ``threading.Condition``
                           (or compatible/equivalent) objects
@@ -412,6 +451,10 @@
                            any user provided callable should not raise
                            exceptions on being called
         :type on_failure: callable
+        :param args: positional arguments to be passed to all callables
+        :type args: tuple
+        :param kwargs: keyword arguments to be passed to all callables
+        :type kwargs: dict
         """
         callables = []
         for obj in objects:
@@ -421,10 +464,7 @@
                 if six.callable(member):
                     missing_attrs = _check_attrs(member)
                     if not missing_attrs:
-                        # These do not support custom args, kwargs...
-                        callables.append((member,
-                                          cls._NO_OP_ARGS,
-                                          cls._NO_OP_KWARGS))
+                        callables.append((member, args, kwargs))
         return cls(callables, log=log, executor_factory=executor_factory,
                    cond_cls=cond_cls, event_cls=event_cls,
                    schedule_strategy=schedule_strategy, now_func=now_func,
@@ -456,7 +496,7 @@
                                  provided one will be created that uses
                                  the :py:class:`~futurist.SynchronousExecutor`
                                  class)
-        :type executor_factory: callable
+        :type executor_factory: ExecutorFactory or any callable
         :param cond_cls: callable object that can
                           produce ``threading.Condition``
                           (or compatible/equivalent) objects
@@ -496,6 +536,7 @@
         self._waiter = cond_cls()
         self._dead = event_cls()
         self._active = event_cls()
+        self._cond_cls = cond_cls
         self._watchers = []
         self._callables = []
         for (cb, args, kwargs) in callables:
@@ -541,6 +582,7 @@
 
     def _run(self, executor, runner):
         """Main worker run loop."""
+        barrier = utils.Barrier(cond_cls=self._cond_cls)
 
         def _process_scheduled():
             # Figure out when we should run next (by selecting the
@@ -567,14 +609,28 @@
                     cb, cb_name, args, kwargs = self._callables[index]
                     self._log.debug("Submitting periodic function '%s'",
                                     cb_name)
-                    fut = executor.submit(runner,
-                                          self._now_func,
-                                          cb, *args, **kwargs)
-                    fut.add_done_callback(functools.partial(_on_done,
-                                                            PERIODIC,
-                                                            cb, cb_name,
-                                                            index,
-                                                            submitted_at))
+                    try:
+                        fut = executor.submit(runner,
+                                              self._now_func,
+                                              cb, *args, **kwargs)
+                    except _SCHEDULE_RETRY_EXCEPTIONS as exc:
+                        # Restart after a short delay
+                        delay = (self._RESCHEDULE_DELAY +
+                                 random().random() * self._RESCHEDULE_JITTER)
+                        self._log.error("Failed to submit periodic function "
+                                        "'%s', retrying after %.2f sec. "
+                                        "Error: %s",
+                                        cb_name, delay, exc)
+                        self._schedule.push(self._now_func() + delay,
+                                            index)
+                    else:
+                        barrier.incr()
+                        fut.add_done_callback(functools.partial(_on_done,
+                                                                PERIODIC,
+                                                                cb, cb_name,
+                                                                index,
+                                                                submitted_at))
+                        fut.add_done_callback(lambda _fut: barrier.decr())
                 else:
                     # Gotta wait...
                     self._schedule.push(next_run, index)
@@ -590,12 +646,22 @@
                 cb, cb_name, args, kwargs = self._callables[index]
                 submitted_at = self._now_func()
                 self._log.debug("Submitting immediate function '%s'", cb_name)
-                fut = executor.submit(runner, self._now_func,
-                                      cb, *args, **kwargs)
-                fut.add_done_callback(functools.partial(_on_done,
-                                                        IMMEDIATE,
-                                                        cb, cb_name,
-                                                        index, submitted_at))
+                try:
+                    fut = executor.submit(runner, self._now_func,
+                                          cb, *args, **kwargs)
+                except _SCHEDULE_RETRY_EXCEPTIONS as exc:
+                    self._log.error("Failed to submit immediate function "
+                                    "'%s', retrying. Error: %s", cb_name, exc)
+                    # Restart as soon as possible
+                    self._immediates.append(index)
+                else:
+                    barrier.incr()
+                    fut.add_done_callback(functools.partial(_on_done,
+                                                            IMMEDIATE,
+                                                            cb, cb_name,
+                                                            index,
+                                                            submitted_at))
+                    fut.add_done_callback(lambda _fut: barrier.decr())
 
         def _on_done(kind, cb, cb_name, index, submitted_at, fut):
             started_at, finished_at, failure = fut.result()
@@ -618,9 +684,12 @@
                 self._schedule.push(next_run, index)
                 self._waiter.notify_all()
 
-        while not self._tombstone.is_set():
-            _process_immediates()
-            _process_scheduled()
+        try:
+            while not self._tombstone.is_set():
+                _process_immediates()
+                _process_scheduled()
+        finally:
+            barrier.wait()
 
     def _on_finish(self):
         # TODO(harlowja): this may be to verbose for people?
@@ -713,7 +782,8 @@
         try:
             self._run(executor, runner)
         finally:
-            executor.shutdown()
+            if getattr(self._executor_factory, 'shutdown', True):
+                executor.shutdown()
             self._dead.set()
             self._active.clear()
             self._on_finish()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/rejection.py 
new/futurist-0.13.0/futurist/rejection.py
--- old/futurist-0.9.0/futurist/rejection.py    2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/futurist/rejection.py   2016-02-23 15:48:56.000000000 
+0100
@@ -23,7 +23,7 @@
     """Returns a function that will raise when backlog goes past max size."""
 
     def _rejector(executor, backlog):
-        if backlog + 1 >= max_backlog:
+        if backlog >= max_backlog:
             raise futurist.RejectedSubmission("Current backlog %s is not"
                                               " allowed to go"
                                               " beyond %s" % (backlog,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/tests/test_executors.py 
new/futurist-0.13.0/futurist/tests/test_executors.py
--- old/futurist-0.9.0/futurist/tests/test_executors.py 2015-12-21 
20:52:23.000000000 +0100
+++ new/futurist-0.13.0/futurist/tests/test_executors.py        2016-02-23 
15:48:56.000000000 +0100
@@ -18,6 +18,7 @@
 from testtools import testcase
 
 import futurist
+from futurist import rejection
 from futurist.tests import base
 
 
@@ -137,3 +138,31 @@
         self.assertEqual(10, len(happy_completed) + len(unhappy_completed))
         self.assertEqual(5, len(unhappy_completed))
         self.assertEqual(5, len(happy_completed))
+
+
+_REJECTION = rejection.reject_when_reached(1)
+
+
+class TestRejection(testscenarios.TestWithScenarios, base.TestCase):
+    scenarios = [
+        ('green', {'executor_cls': futurist.GreenThreadPoolExecutor,
+                   'executor_kwargs': {'check_and_reject': _REJECTION,
+                                       'max_workers': 1}}),
+        ('thread', {'executor_cls': futurist.ThreadPoolExecutor,
+                    'executor_kwargs': {'check_and_reject': _REJECTION,
+                                        'max_workers': 1}}),
+    ]
+
+    def setUp(self):
+        super(TestRejection, self).setUp()
+        self.executor = self.executor_cls(**self.executor_kwargs)
+
+    def test_rejection(self):
+        self.addCleanup(self.executor.shutdown)
+
+        # 1 worker + 1 item of backlog
+        for _i in range(2):
+            self.executor.submit(delayed, 0.5)
+
+        self.assertRaises(futurist.RejectedSubmission,
+                          self.executor.submit, returns_one)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist/tests/test_periodics.py 
new/futurist-0.13.0/futurist/tests/test_periodics.py
--- old/futurist-0.9.0/futurist/tests/test_periodics.py 2015-12-21 
20:52:23.000000000 +0100
+++ new/futurist-0.13.0/futurist/tests/test_periodics.py        2016-02-23 
15:48:56.000000000 +0100
@@ -19,6 +19,7 @@
 
 import eventlet
 from eventlet.green import threading as green_threading
+import mock
 import testscenarios
 
 import futurist
@@ -234,6 +235,21 @@
         self.assertIsNotNone(w.add(add_me))
         self.assertEqual(1, len(w))
 
+    def test_is_periodic(self):
+
+        @periodics.periodic(0.5, enabled=False)
+        def no_add_me():
+            pass
+
+        @periodics.periodic(0.5)
+        def add_me():
+            pass
+
+        self.assertTrue(periodics.is_periodic(add_me))
+        self.assertTrue(periodics.is_periodic(no_add_me))
+        self.assertFalse(periodics.is_periodic(self.test_is_periodic))
+        self.assertFalse(periodics.is_periodic(42))
+
     def test_watcher(self):
 
         def cb():
@@ -272,7 +288,32 @@
             (every_one_sec, (cb,), None),
             (every_half_sec, (cb,), None),
         ]
-        executor_factory = lambda: self.executor_cls(**self.executor_kwargs)
+        executor = self.executor_cls(**self.executor_kwargs)
+        executor_factory = lambda: executor
+        w = periodics.PeriodicWorker(callables,
+                                     executor_factory=executor_factory,
+                                     **self.worker_kwargs)
+        with self.create_destroy(w.start):
+            self.sleep(2.0)
+            w.stop()
+
+        am_called = sum(called)
+        self.assertGreaterEqual(am_called, 4)
+
+        self.assertFalse(executor.alive)
+
+    def test_existing_executor(self):
+        called = []
+
+        def cb():
+            called.append(1)
+
+        callables = [
+            (every_one_sec, (cb,), None),
+            (every_half_sec, (cb,), None),
+        ]
+        executor = self.executor_cls(**self.executor_kwargs)
+        executor_factory = periodics.ExistingExecutor(executor)
         w = periodics.PeriodicWorker(callables,
                                      executor_factory=executor_factory,
                                      **self.worker_kwargs)
@@ -281,4 +322,64 @@
             w.stop()
 
         am_called = sum(called)
+        self.assertGreaterEqual(am_called, 4)
+
+        self.assertTrue(executor.alive)
+
+    def test_create_with_arguments(self):
+        m = mock.Mock()
+
+        class Object(object):
+            @periodics.periodic(0.5)
+            def func1(self, *args, **kwargs):
+                m(*args, **kwargs)
+
+        executor_factory = lambda: self.executor_cls(**self.executor_kwargs)
+        w = periodics.PeriodicWorker.create(objects=[Object()],
+                                            executor_factory=executor_factory,
+                                            args=('foo',),
+                                            kwargs={'bar': 'baz'},
+                                            **self.worker_kwargs)
+        with self.create_destroy(w.start):
+            self.sleep(2.0)
+            w.stop()
+
+        m.assert_called_with('foo', bar='baz')
+
+
+class RejectingExecutor(futurist.GreenThreadPoolExecutor):
+    MAX_REJECTIONS_COUNT = 2
+
+    def _reject(self, *args):
+        if self._rejections_count < self.MAX_REJECTIONS_COUNT:
+            self._rejections_count += 1
+            raise futurist.RejectedSubmission()
+
+    def __init__(self):
+        self._rejections_count = 0
+        super(RejectingExecutor, self).__init__(check_and_reject=self._reject)
+
+
+class TestRetrySubmission(base.TestCase):
+    def test_retry_submission(self):
+        called = []
+
+        def cb():
+            called.append(1)
+
+        callables = [
+            (every_one_sec, (cb,), None),
+            (every_half_sec, (cb,), None),
+        ]
+        w = periodics.PeriodicWorker(callables,
+                                     executor_factory=RejectingExecutor,
+                                     cond_cls=green_threading.Condition,
+                                     event_cls=green_threading.Event)
+        w._RESCHEDULE_DELAY = 0
+        w._RESCHEDULE_JITTER = 0
+        with create_destroy_green_thread(w.start):
+            eventlet.sleep(2.0)
+            w.stop()
+
+        am_called = sum(called)
         self.assertGreaterEqual(am_called, 4)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist.egg-info/PKG-INFO 
new/futurist-0.13.0/futurist.egg-info/PKG-INFO
--- old/futurist-0.9.0/futurist.egg-info/PKG-INFO       2015-12-21 
20:52:56.000000000 +0100
+++ new/futurist-0.13.0/futurist.egg-info/PKG-INFO      2016-02-23 
15:49:16.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: futurist
-Version: 0.9.0
+Version: 0.13.0
 Summary: Useful additions to futures, from the future.
 Home-page: http://www.openstack.org/
 Author: OpenStack
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist.egg-info/pbr.json 
new/futurist-0.13.0/futurist.egg-info/pbr.json
--- old/futurist-0.9.0/futurist.egg-info/pbr.json       2015-12-21 
20:52:56.000000000 +0100
+++ new/futurist-0.13.0/futurist.egg-info/pbr.json      2016-02-23 
15:49:16.000000000 +0100
@@ -1 +1 @@
-{"is_release": true, "git_version": "d9231f5"}
\ No newline at end of file
+{"is_release": true, "git_version": "bd9f7ca"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/futurist.egg-info/requires.txt 
new/futurist-0.13.0/futurist.egg-info/requires.txt
--- old/futurist-0.9.0/futurist.egg-info/requires.txt   2015-12-21 
20:52:56.000000000 +0100
+++ new/futurist-0.13.0/futurist.egg-info/requires.txt  2016-02-23 
15:49:16.000000000 +0100
@@ -1,6 +1,6 @@
 pbr>=1.6
 six>=1.9.0
-monotonic>=0.3
+monotonic>=0.6
 contextlib2>=0.4.0
 
 [:(python_version=='2.7' or python_version=='2.6')]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/requirements.txt 
new/futurist-0.13.0/requirements.txt
--- old/futurist-0.9.0/requirements.txt 2015-12-21 20:52:23.000000000 +0100
+++ new/futurist-0.13.0/requirements.txt        2016-02-23 15:48:56.000000000 
+0100
@@ -2,8 +2,8 @@
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
 
-pbr>=1.6
-six>=1.9.0
-monotonic>=0.3 # Apache-2.0
-futures>=3.0;python_version=='2.7' or python_version=='2.6'
+pbr>=1.6 # Apache-2.0
+six>=1.9.0 # MIT
+monotonic>=0.6 # Apache-2.0
+futures>=3.0;python_version=='2.7' or python_version=='2.6' # BSD
 contextlib2>=0.4.0 # PSF License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/setup.cfg 
new/futurist-0.13.0/setup.cfg
--- old/futurist-0.9.0/setup.cfg        2015-12-21 20:52:56.000000000 +0100
+++ new/futurist-0.13.0/setup.cfg       2016-02-23 15:49:16.000000000 +0100
@@ -52,6 +52,6 @@
 
 [egg_info]
 tag_build = 
-tag_date = 0
 tag_svn_revision = 0
+tag_date = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/test-requirements.txt 
new/futurist-0.13.0/test-requirements.txt
--- old/futurist-0.9.0/test-requirements.txt    2015-12-21 20:52:23.000000000 
+0100
+++ new/futurist-0.13.0/test-requirements.txt   2016-02-23 15:48:56.000000000 
+0100
@@ -5,15 +5,15 @@
 hacking<0.11,>=0.10.0
 
 # Used for making sure the eventlet executors work.
-eventlet>=0.17.4
+eventlet!=0.18.3,>=0.18.2 # MIT
 
 doc8 # Apache-2.0
-coverage>=3.6
-discover
-python-subunit>=0.0.18
-sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
+coverage>=3.6 # Apache-2.0
+discover # BSD
+python-subunit>=0.0.18 # Apache-2.0/BSD
+sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
 oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
 oslotest>=1.10.0 # Apache-2.0
-testrepository>=0.0.18
-testscenarios>=0.4
-testtools>=1.4.0
+testrepository>=0.0.18 # Apache-2.0/BSD
+testscenarios>=0.4 # Apache-2.0/BSD
+testtools>=1.4.0 # MIT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/futurist-0.9.0/tox.ini new/futurist-0.13.0/tox.ini
--- old/futurist-0.9.0/tox.ini  2015-12-21 20:52:23.000000000 +0100
+++ new/futurist-0.13.0/tox.ini 2016-02-23 15:48:56.000000000 +0100
@@ -1,6 +1,6 @@
 [tox]
 minversion = 1.6
-envlist = py33,py34,py26,py27,pypy,pep8
+envlist = py34,py27,pypy,pep8
 skipsdist = True
 
 [testenv]


Reply via email to