summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-02-12 21:01:59 +0000
committerGerrit Code Review <review@openstack.org>2015-02-12 21:01:59 +0000
commitf11f7bbda725578312be53a8baf174715e1f80bd (patch)
treef839f854729f31162d5199fe8397ed95bad4a2e9
parentc6d57a022793e9195dd3355bbfd35e8c96c6dd64 (diff)
parentb7d59ec7484f159db2cce3dc89ae3f784e821bb2 (diff)
downloadtaskflow-f11f7bbda725578312be53a8baf174715e1f80bd.tar.gz
Merge "Docstrings should document parameters return values"
-rw-r--r--taskflow/types/failure.py6
-rw-r--r--taskflow/types/fsm.py84
-rw-r--r--taskflow/types/futures.py46
-rw-r--r--taskflow/types/latch.py9
-rw-r--r--taskflow/types/notifier.py65
-rw-r--r--taskflow/types/periodic.py7
-rw-r--r--taskflow/types/table.py11
-rw-r--r--taskflow/types/timing.py10
-rw-r--r--taskflow/types/tree.py10
9 files changed, 200 insertions, 48 deletions
diff --git a/taskflow/types/failure.py b/taskflow/types/failure.py
index 0f45bc3..7df0f68 100644
--- a/taskflow/types/failure.py
+++ b/taskflow/types/failure.py
@@ -175,7 +175,11 @@ class Failure(object):
and self.traceback_str == other.traceback_str)
def matches(self, other):
- """Checks if another object is equivalent to this object."""
+ """Checks if another object is equivalent to this object.
+
+ :returns: checks if another object is equivalent to this object
+ :rtype: boolean
+ """
if not isinstance(other, Failure):
return False
if self.exc_info is None or other.exc_info is None:
diff --git a/taskflow/types/fsm.py b/taskflow/types/fsm.py
index 6ca2290..df61476 100644
--- a/taskflow/types/fsm.py
+++ b/taskflow/types/fsm.py
@@ -76,13 +76,23 @@ class FSM(object):
@property
def current_state(self):
+ """Return the current state name.
+
+ :returns: current state name
+ :rtype: string
+ """
if self._current is not None:
return self._current.name
return None
@property
def terminated(self):
- """Returns whether the state machine is in a terminal state."""
+ """Returns whether the state machine is in a terminal state.
+
+ :returns: whether the state machine is in
+ terminal state or not
+ :rtype: boolean
+ """
if self._current is None:
return False
return self._states[self._current.name]['terminal']
@@ -90,11 +100,16 @@ class FSM(object):
def add_state(self, state, terminal=False, on_enter=None, on_exit=None):
"""Adds a given state to the state machine.
- The on_enter and on_exit callbacks, if provided will be expected to
- take two positional parameters, these being the state being exited (for
- on_exit) or the state being entered (for on_enter) and a second
- parameter which is the event that is being processed that caused the
- state transition.
+ :param on_enter: callback, if provided will be expected to take
+ two positional parameters, these being state being
+ entered and the second parameter is the event that is
+ being processed that caused the state transition
+ :param on_exit: callback, if provided will be expected to take
+ two positional parameters, these being state being
+ entered and the second parameter is the event that is
+ being processed that caused the state transition
+ :param state: state being entered or exited
+ :type state: string
"""
if self.frozen:
raise FrozenMachine()
@@ -117,22 +132,22 @@ class FSM(object):
def add_reaction(self, state, event, reaction, *args, **kwargs):
"""Adds a reaction that may get triggered by the given event & state.
+ :param state: the last stable state expressed
+ :type state: string
+ :param event: event that caused the transition
+ :param args: non-keyworded arguments
+ :type args: list
+ :param kwargs: key-value pair arguments
+ :type kwargs: dictionary
+
Reaction callbacks may (depending on how the state machine is ran) be
- used after an event is processed (and a transition occurs) to cause the
- machine to react to the newly arrived at stable state.
-
- These callbacks are expected to accept three default positional
- parameters (although more can be passed in via *args and **kwargs,
- these will automatically get provided to the callback when it is
- activated *ontop* of the three default). The three default parameters
- are the last stable state, the new stable state and the event that
- caused the transition to this new stable state to be arrived at.
-
- The expected result of a callback is expected to be a new event that
- the callback wants the state machine to react to. This new event
- may (depending on how the state machine is ran) get processed (and
- this process typically repeats) until the state machine reaches a
- terminal state.
+ used after an event is processed (and a transition occurs) to cause
+ the machine to react to the newly arrived at stable state. The
+ expected result of a callback is expected to be a
+ new event that the callback wants the state machine to react to.
+ This new event may (depending on how the state machine is ran) get
+ processed (and this process typically repeats) until the state
+ machine reaches a terminal state.
"""
if self.frozen:
raise FrozenMachine()
@@ -148,7 +163,12 @@ class FSM(object):
" already defined" % (state, event))
def add_transition(self, start, end, event):
- """Adds an allowed transition from start -> end for the given event."""
+ """Adds an allowed transition from start -> end for the given event.
+
+ :param start: start of the transition
+ :param end: end of the transition
+ :param event: event that caused the transition
+ """
if self.frozen:
raise FrozenMachine()
if start not in self._states:
@@ -164,7 +184,10 @@ class FSM(object):
self._states[start]['on_exit'])
def process_event(self, event):
- """Trigger a state change in response to the provided event."""
+ """Trigger a state change in response to the provided event.
+
+ :param event: event to be processed to cause a potential transition
+ """
current = self._current
if current is None:
raise NotInitialized("Can only process events after"
@@ -256,7 +279,14 @@ class FSM(object):
event = cb(old_state, new_state, event, *args, **kwargs)
def __contains__(self, state):
- """Returns if this state exists in the machines known states."""
+ """Returns if this state exists in the machines known states.
+
+ :param state: input state
+ :type state: string
+ :returns: checks whether the state exists in the machine
+ known states
+ :rtype: boolean
+ """
return state in self._states
def freeze(self):
@@ -270,7 +300,11 @@ class FSM(object):
@property
def events(self):
- """Returns how many events exist."""
+ """Returns how many events exist.
+
+ :returns: how many events exist
+ :rtype: number
+ """
c = 0
for state in six.iterkeys(self._states):
c += len(self._transitions[state])
diff --git a/taskflow/types/futures.py b/taskflow/types/futures.py
index 1d847dd..2a6f7b6 100644
--- a/taskflow/types/futures.py
+++ b/taskflow/types/futures.py
@@ -54,6 +54,11 @@ class _Gatherer(object):
self._stats = ExecutorStatistics()
def _capture_stats(self, watch, fut):
+ """Capture statistics
+
+ :param watch: stopwatch object
+ :param fut: future object
+ """
watch.stop()
with self._stats_lock:
# Use a new collection and lock so that all mutations are seen as
@@ -79,6 +84,7 @@ class _Gatherer(object):
cancelled=cancelled)
def submit(self, fn, *args, **kwargs):
+ """Submit work to be executed and capture statistics."""
watch = timing.StopWatch()
if self._start_before_submit:
watch.start()
@@ -301,7 +307,13 @@ class GreenThreadPoolExecutor(_futures.Executor):
return self._gatherer.statistics
def submit(self, fn, *args, **kwargs):
- """Submit some work to be executed (and gather statistics)."""
+ """Submit some work to be executed (and gather statistics).
+
+ :param args: non-keyworded arguments
+ :type args: list
+ :param kwargs: key-value arguments
+ :type kwargs: dictionary
+ """
with self._shutdown_lock:
if self._shutdown:
raise RuntimeError('Can not schedule new futures'
@@ -316,6 +328,12 @@ class GreenThreadPoolExecutor(_futures.Executor):
return f
def _spin_up(self, work):
+ """Spin up a greenworker if less than max_workers.
+
+ :param work: work to be given to the greenworker
+ :returns: whether a green worker was spun up or not
+ :rtype: boolean
+ """
alive = self._pool.running() + self._pool.waiting()
if alive < self._max_workers:
self._pool.spawn_n(_GreenWorker(self, work, self._delayed_work))
@@ -350,28 +368,46 @@ class ExecutorStatistics(object):
@property
def failures(self):
- """How many submissions ended up raising exceptions."""
+ """How many submissions ended up raising exceptions.
+
+ :returns: how many submissions ended up raising exceptions
+ :rtype: number
+ """
return self._failures
@property
def executed(self):
- """How many submissions were executed (failed or not)."""
+ """How many submissions were executed (failed or not).
+
+ :returns: how many submissions were executed
+ :rtype: number
+ """
return self._executed
@property
def runtime(self):
- """Total runtime of all submissions executed (failed or not)."""
+ """Total runtime of all submissions executed (failed or not).
+
+ :returns: total runtime of all submissions executed
+ :rtype: number
+ """
return self._runtime
@property
def cancelled(self):
- """How many submissions were cancelled before executing."""
+ """How many submissions were cancelled before executing.
+
+ :returns: how many submissions were cancelled before executing
+ :rtype: number
+ """
return self._cancelled
@property
def average_runtime(self):
"""The average runtime of all submissions executed.
+ :returns: average runtime of all submissions executed
+ :rtype: number
:raises: ZeroDivisionError when no executions have occurred.
"""
return self._runtime / self._executed
diff --git a/taskflow/types/latch.py b/taskflow/types/latch.py
index 3e27978..0778330 100644
--- a/taskflow/types/latch.py
+++ b/taskflow/types/latch.py
@@ -49,10 +49,11 @@ class Latch(object):
def wait(self, timeout=None):
"""Waits until the latch is released.
- NOTE(harlowja): if a timeout is provided this function will wait
- until that timeout expires, if the latch has been released before the
- timeout expires then this will return True, otherwise it will
- return False.
+ :param timeout: wait until the timeout expires
+ :type timeout: number
+ :returns: true if the latch has been released before the
+ timeout expires otherwise false
+ :rtype: boolean
"""
watch = tt.StopWatch(duration=timeout)
watch.start()
diff --git a/taskflow/types/notifier.py b/taskflow/types/notifier.py
index 9f4df80..77dbbc0 100644
--- a/taskflow/types/notifier.py
+++ b/taskflow/types/notifier.py
@@ -29,6 +29,18 @@ class _Listener(object):
"""Internal helper that represents a notification listener/target."""
def __init__(self, callback, args=None, kwargs=None, details_filter=None):
+ """Initialize members
+
+ :param callback: callback function
+ :param details_filter: a callback that will be called before the
+ actual callback that can be used to discard
+ the event (thus avoiding the invocation of
+ the actual callback)
+ :param args: non-keyworded arguments
+ :type args: list
+ :param kwargs: key-value pair arguments
+ :type kwargs: dictionary
+ """
self._callback = callback
self._details_filter = details_filter
if not args:
@@ -64,6 +76,13 @@ class _Listener(object):
return "<%s>" % repr_msg
def is_equivalent(self, callback, details_filter=None):
+ """Check if the callback is same
+
+ :param callback: callback used for comparison
+ :param details_filter: callback used for comparison
+ :returns: false if not the same callback, otherwise true
+ :rtype: boolean
+ """
if not reflection.is_same_callback(self._callback, callback):
return False
if details_filter is not None:
@@ -105,14 +124,22 @@ class Notifier(object):
self._listeners = collections.defaultdict(list)
def __len__(self):
- """Returns how many callbacks are registered."""
+ """Returns how many callbacks are registered.
+
+ :returns: count of how many callbacks are registered
+ :rtype: number
+ """
count = 0
for (_event_type, listeners) in six.iteritems(self._listeners):
count += len(listeners)
return count
def is_registered(self, event_type, callback, details_filter=None):
- """Check if a callback is registered."""
+ """Check if a callback is registered.
+
+ :returns: checks if the callback is registered
+ :rtype: boolean
+ """
for listener in self._listeners.get(event_type, []):
if listener.is_equivalent(callback, details_filter=details_filter):
return True
@@ -134,7 +161,8 @@ class Notifier(object):
:param event_type: event type that occurred
:param details: additional event details *dictionary* passed to
- callback keyword argument with the same name.
+ callback keyword argument with the same name
+ :type details: dictionary
"""
if not self.can_trigger_notification(event_type):
LOG.debug("Event type '%s' is not allowed to trigger"
@@ -165,6 +193,13 @@ class Notifier(object):
:meth:`.notify` method (if a details filter callback is provided then
the target callback will *only* be triggered if the details filter
callback returns a truthy value).
+
+ :param event_type: event type input
+ :param callback: function callback to be registered.
+ :param args: non-keyworded arguments
+ :type args: list
+ :param kwargs: key-value pair arguments
+ :type kwargs: dictionary
"""
if not six.callable(callback):
raise ValueError("Event callback must be callable")
@@ -189,7 +224,10 @@ class Notifier(object):
details_filter=details_filter))
def deregister(self, event_type, callback, details_filter=None):
- """Remove a single listener bound to event ``event_type``."""
+ """Remove a single listener bound to event ``event_type``.
+
+ :param event_type: deregister listener bound to event_type
+ """
if event_type not in self._listeners:
return False
for i, listener in enumerate(self._listeners.get(event_type, [])):
@@ -199,7 +237,10 @@ class Notifier(object):
return False
def deregister_event(self, event_type):
- """Remove a group of listeners bound to event ``event_type``."""
+ """Remove a group of listeners bound to event ``event_type``.
+
+ :param event_type: deregister listeners bound to event_type
+ """
return len(self._listeners.pop(event_type, []))
def copy(self):
@@ -220,7 +261,12 @@ class Notifier(object):
return True
def can_trigger_notification(self, event_type):
- """Checks if the event can trigger a notification."""
+ """Checks if the event can trigger a notification.
+
+ :param event_type: event that needs to be verified
+ :returns: whether the event can trigger a notification
+ :rtype: boolean
+ """
if event_type in self._DISALLOWED_NOTIFICATION_EVENTS:
return False
else:
@@ -251,7 +297,12 @@ class RestrictedNotifier(Notifier):
yield event_type
def can_be_registered(self, event_type):
- """Checks if the event can be registered/subscribed to."""
+ """Checks if the event can be registered/subscribed to.
+
+ :param event_type: event that needs to be verified
+ :returns: whether the event can be registered/subscribed to
+ :rtype: boolean
+ """
return (event_type in self._watchable_events or
(event_type == self.ANY and self._allow_any))
diff --git a/taskflow/types/periodic.py b/taskflow/types/periodic.py
index f00d97e..9237d9c 100644
--- a/taskflow/types/periodic.py
+++ b/taskflow/types/periodic.py
@@ -39,7 +39,12 @@ _PERIODIC_ATTRS = tuple([
def periodic(spacing, run_immediately=True):
- """Tags a method/function as wanting/able to execute periodically."""
+ """Tags a method/function as wanting/able to execute periodically.
+
+ :param run_immediately: option to specify whether to run
+ immediately or not
+ :type run_immediately: boolean
+ """
if spacing <= 0:
raise ValueError("Periodicity/spacing must be greater than"
diff --git a/taskflow/types/table.py b/taskflow/types/table.py
index e074e95..5966051 100644
--- a/taskflow/types/table.py
+++ b/taskflow/types/table.py
@@ -51,8 +51,15 @@ class PleasantTable(object):
@classmethod
def _size_selector(cls, possible_sizes):
- # The number two is used so that the edges of a column have spaces
- # around them (instead of being right next to a column separator).
+ """Select the maximum size, utility function for adding borders.
+
+ The number two is used so that the edges of a column have spaces
+ around them (instead of being right next to a column separator).
+
+ :param possible_sizes: possible sizes available
+ :returns: maximum size
+ :rtype: number
+ """
try:
return max(x + 2 for x in possible_sizes)
except ValueError:
diff --git a/taskflow/types/timing.py b/taskflow/types/timing.py
index da3938d..e22b2da 100644
--- a/taskflow/types/timing.py
+++ b/taskflow/types/timing.py
@@ -250,8 +250,10 @@ class StopWatch(object):
:param return_none: when ``True`` instead of raising a ``RuntimeError``
when no duration has been set this call will
- return ``None`` instead.
+ return ``None`` instead
:type return_none: boolean
+ :returns: how many seconds left until the watch expires
+ :rtype: number
"""
if self._state != self._STARTED:
raise RuntimeError("Can not get the leftover time of a stopwatch"
@@ -265,7 +267,11 @@ class StopWatch(object):
return max(0.0, self._duration - self.elapsed())
def expired(self):
- """Returns if the watch has expired (ie, duration provided elapsed)."""
+ """Returns if the watch has expired (ie, duration provided elapsed).
+
+ :returns: if the watch has expired
+ :rtype: boolean
+ """
if self._state is None:
raise RuntimeError("Can not check if a stopwatch has expired"
" if it has not been started/stopped")
diff --git a/taskflow/types/tree.py b/taskflow/types/tree.py
index 2386bc9..30edd45 100644
--- a/taskflow/types/tree.py
+++ b/taskflow/types/tree.py
@@ -102,6 +102,9 @@ class Node(object):
This will search not only this node but also any children nodes and
finally if nothing is found then None is returned instead of a node
object.
+
+ :param item: item to lookup.
+ :returns: the node for an item if it exists in this node
"""
for n in self.dfs_iter(include_self=True):
if n.item == item:
@@ -109,7 +112,12 @@ class Node(object):
return None
def __contains__(self, item):
- """Returns if this item exists in this node or this nodes children."""
+ """Returns whether item exists in this node or this nodes children.
+
+ :returns: if the item exists in this node or nodes children,
+ true if the item exists, false otherwise
+ :rtype: boolean
+ """
return self.find(item) is not None
def __getitem__(self, index):