Merge "Docstrings should document parameters return values"
This commit is contained in:
@@ -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:
|
||||
|
@@ -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])
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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))
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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:
|
||||
|
@@ -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")
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user