summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZane Bitter <zbitter@redhat.com>2017-10-18 16:46:39 -0400
committerZane Bitter <zbitter@redhat.com>2017-10-18 16:46:39 -0400
commit6a9672a26443c901f4a465c86992ecece3f73bbd (patch)
tree0948ccc957454786f0437e1be293e31ae367a87b
parentfe45b745e5f0a859f10b6edf2ad8f1e24cc01a56 (diff)
downloadheat-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.py17
-rw-r--r--heat/tests/engine/test_scheduler.py6
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):