diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-02-12 21:01:59 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-02-12 21:01:59 +0000 |
commit | f11f7bbda725578312be53a8baf174715e1f80bd (patch) | |
tree | f839f854729f31162d5199fe8397ed95bad4a2e9 | |
parent | c6d57a022793e9195dd3355bbfd35e8c96c6dd64 (diff) | |
parent | b7d59ec7484f159db2cce3dc89ae3f784e821bb2 (diff) | |
download | taskflow-f11f7bbda725578312be53a8baf174715e1f80bd.tar.gz |
Merge "Docstrings should document parameters return values"
-rw-r--r-- | taskflow/types/failure.py | 6 | ||||
-rw-r--r-- | taskflow/types/fsm.py | 84 | ||||
-rw-r--r-- | taskflow/types/futures.py | 46 | ||||
-rw-r--r-- | taskflow/types/latch.py | 9 | ||||
-rw-r--r-- | taskflow/types/notifier.py | 65 | ||||
-rw-r--r-- | taskflow/types/periodic.py | 7 | ||||
-rw-r--r-- | taskflow/types/table.py | 11 | ||||
-rw-r--r-- | taskflow/types/timing.py | 10 | ||||
-rw-r--r-- | taskflow/types/tree.py | 10 |
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): |