+def to_seconds(**kwd):
+ if "milliseconds" in kwd:
+ return kwd["milliseconds"] / 1000
+ elif "seconds" in kwd:
+ return kwd["seconds"]
+ elif "minutes" in kwd:
+ return kwd["minutes"] * 60
+ elif "hours" in kwd:
+ return kwd["hours"] * 60 * 60
+ raise KeyError("Unknown arg: %r" % kwd)
+
+
+class NopStateStrategy(object):
+
+ def __init__(self):
+ pass
+
+ def initialize_state(self):
+ pass
+
+ def reinitialize_state(self):
+ pass
+
+ def increment_state(self):
+ pass
+
+ @property
+ def timeout(self):
+ return UpdateStateMachine.INFINITE_PERIOD
+
+ def __repr__(self):
+ return "NopStateStrategy()"
+
+
+class ConstantStateStrategy(object):
+
+ def __init__(self, timeout):
+ assert 0 < timeout or timeout == UpdateStateMachine.INFINITE_PERIOD
+ self._timeout = timeout
+
+ def initialize_state(self):
+ pass
+
+ def reinitialize_state(self):
+ pass
+
+ def increment_state(self):
+ pass
+
+ @property
+ def timeout(self):
+ return self._timeout
+
+ def __repr__(self):
+ return "ConstantStateStrategy(timeout=%r)" % self._timeout
+
+
+class NTimesStateStrategy(object):
+
+ def __init__(self, timeouts, postTimeout):
+ assert 0 < len(timeouts)
+ for timeout in timeouts:
+ assert 0 < timeout or timeout == UpdateStateMachine.INFINITE_PERIOD
+ assert 0 < postTimeout or postTimeout == UpdateStateMachine.INFINITE_PERIOD
+ self._timeouts = timeouts
+ self._postTimeout = postTimeout
+
+ self._attemptCount = 0
+
+ def initialize_state(self):
+ self._attemptCount = len(self._timeouts)
+
+ def reinitialize_state(self):
+ self._attemptCount = 0
+
+ def increment_state(self):
+ self._attemptCount += 1
+
+ @property
+ def timeout(self):
+ try:
+ return self._timeouts[self._attemptCount]
+ except IndexError:
+ return self._postTimeout
+
+ def __str__(self):
+ return "NTimesStateStrategy(timeout=%r)" % (
+ self.timeout,
+ )
+
+ def __repr__(self):
+ return "NTimesStateStrategy(timeouts=%r, postTimeout=%r)" % (
+ self._timeouts,
+ self._postTimeout,
+ )
+
+
+class GeometricStateStrategy(object):
+
+ def __init__(self, init, min, max):
+ assert 0 < init and init < max or init == UpdateStateMachine.INFINITE_PERIOD
+ assert 0 < min or min == UpdateStateMachine.INFINITE_PERIOD
+ assert min < max or max == UpdateStateMachine.INFINITE_PERIOD
+ self._min = min
+ self._max = max
+ self._init = init
+ self._current = 0
+
+ def initialize_state(self):
+ self._current = self._max
+
+ def reinitialize_state(self):
+ self._current = self._min
+
+ def increment_state(self):
+ if self._current == UpdateStateMachine.INFINITE_PERIOD:
+ pass
+ if self._init == UpdateStateMachine.INFINITE_PERIOD:
+ self._current = UpdateStateMachine.INFINITE_PERIOD
+ elif self._max == UpdateStateMachine.INFINITE_PERIOD:
+ self._current *= 2
+ else:
+ self._current = min(2 * self._current, self._max - self._init)
+
+ @property
+ def timeout(self):
+ if UpdateStateMachine.INFINITE_PERIOD in (self._init, self._current):
+ timeout = UpdateStateMachine.INFINITE_PERIOD
+ else:
+ timeout = self._init + self._current
+ return timeout
+
+ def __str__(self):
+ return "GeometricStateStrategy(timeout=%r)" % (
+ self.timeout
+ )
+
+ def __repr__(self):
+ return "GeometricStateStrategy(init=%r, min=%r, max=%r)" % (
+ self._init, self._min, self._max
+ )
+
+