diff options
author | Zane Bitter <zbitter@redhat.com> | 2017-10-18 16:46:39 -0400 |
---|---|---|
committer | Zane Bitter <zbitter@redhat.com> | 2017-10-18 16:46:39 -0400 |
commit | 6a9672a26443c901f4a465c86992ecece3f73bbd (patch) | |
tree | 0948ccc957454786f0437e1be293e31ae367a87b | |
parent | fe45b745e5f0a859f10b6edf2ad8f1e24cc01a56 (diff) | |
download | heat-6a9672a26443c901f4a465c86992ecece3f73bbd.tar.gz |
Make scheduler.Timeout exception hashable
The python standard library in Python 3.6.3 and earlier has a bug with
handling unhashable exceptions: https://bugs.python.org/issue28603
Although oslo_log will catch the error, make scheduler.Timeout hashable so
that all exceptions will be printable.
Prior to 640abe0c12e63c207fcf67592838f112a29f5b43 we just used __cmp__(),
but that isn't used in Python 3. Defining __eq__(), which is required for
the total_ordering decorator, makes the class unhashable in Python 3.
Change-Id: Idde65b2d41490ab8318b5a8b95ea74e9b96b4e5c
Related-Bug: #1724366
Related-Bug: #1721654
-rw-r--r-- | heat/engine/scheduler.py | 17 | ||||
-rw-r--r-- | heat/tests/engine/test_scheduler.py | 6 |
2 files changed, 8 insertions, 15 deletions
diff --git a/heat/engine/scheduler.py b/heat/engine/scheduler.py index d7b120964..5c72d13a1 100644 --- a/heat/engine/scheduler.py +++ b/heat/engine/scheduler.py @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. -import functools import sys import types @@ -47,7 +46,6 @@ def task_description(task): return encodeutils.safe_decode(repr(task)) -@functools.total_ordering class Timeout(BaseException): """Raised when task has exceeded its allotted (wallclock) running time. @@ -78,14 +76,11 @@ class Timeout(BaseException): generator.close() return False - def __eq__(self, other): - if not isinstance(other, Timeout): - return NotImplemented - return not (self < other or other < self) + def earlier_than(self, other): + if other is None: + return True - def __lt__(self, other): - if not isinstance(other, Timeout): - return NotImplemented + assert isinstance(other, Timeout), "Invalid type for Timeout compare" return self._duration.endtime() < other._duration.endtime() @@ -245,7 +240,7 @@ class TaskRunner(object): else: if timeout is not None: new_timeout = Timeout(self, timeout) - if self._timeout is None or new_timeout < self._timeout: + if new_timeout.earlier_than(self._timeout): self._timeout = new_timeout done = self.step() if resuming else self.done() @@ -281,7 +276,7 @@ class TaskRunner(object): self._runner.close() else: timeout = TimedCancel(self, grace_period) - if self._timeout is None or timeout < self._timeout: + if timeout.earlier_than(self._timeout): self._timeout = timeout def started(self): diff --git a/heat/tests/engine/test_scheduler.py b/heat/tests/engine/test_scheduler.py index 83fea5b66..68b9657a3 100644 --- a/heat/tests/engine/test_scheduler.py +++ b/heat/tests/engine/test_scheduler.py @@ -1283,10 +1283,8 @@ class TimeoutTest(common.HeatTestCase): eventlet.sleep(0.01) later = scheduler.Timeout(task, 10) - self.assertLess(earlier, later) - self.assertGreater(later, earlier) - self.assertEqual(earlier, earlier) - self.assertNotEqual(earlier, later) + self.assertTrue(earlier.earlier_than(later)) + self.assertFalse(later.earlier_than(earlier)) class DescriptionTest(common.HeatTestCase): |