Document more function/class/method params

To help fill out the docs start adding on docstrings
that document what a parameter is and what its meaning
and usage is to help users better understand the parameter.

Part of ongoing bug 1374202

Change-Id: I9f9a83cfb763a0a05d22efca4e0f80627ba8ca8f
This commit is contained in:
Joshua Harlow
2014-09-25 14:55:28 -07:00
parent 7f375a86b3
commit 9537f52351
4 changed files with 103 additions and 62 deletions

View File

@@ -125,7 +125,7 @@ class Atom(object):
with this atom. It can be useful in resuming older versions
of atoms. Standard major, minor versioning concepts
should apply.
:ivar save_as: An *immutable* output ``resource`` name dict this atom
:ivar save_as: An *immutable* output ``resource`` name dictionary this atom
produces that other atoms may depend on this atom providing.
The format is output index (or key when a dictionary
is returned from the execute method) to stored argument
@@ -136,11 +136,19 @@ class Atom(object):
the names that this atom expects (in a way this is like
remapping a namespace of another atom into the namespace
of this atom).
:ivar inject: An *immutable* input_name => value dictionary which specifies
any initial inputs that should be automatically injected into
the atoms scope before the atom execution commences (this
allows for providing atom *local* values that do not need to
be provided by other atoms).
:param name: Meaningful name for this atom, should be something that is
distinguishable and understandable for notification,
debugging, storing and any other similar purposes.
:param provides: A set, string or list of items that
this will be providing (or could provide) to others, used
to correlate and associate the thing/s this atom
produces, if it produces anything at all.
:param inject: An *immutable* input_name => value dictionary which
specifies any initial inputs that should be automatically
injected into the atoms scope before the atom execution
commences (this allows for providing atom *local* values that
do not need to be provided by other atoms/dependents).
:ivar inject: See parameter ``inject``.
"""
def __init__(self, name=None, provides=None, inject=None):

View File

@@ -25,6 +25,14 @@ class TaskFlowException(Exception):
NOTE(harlowja): in later versions of python we can likely remove the need
to have a cause here as PY3+ have implemented PEP 3134 which handles
chaining in a much more elegant manner.
:param message: the exception message, typically some string that is
useful for consumers to view when debugging or analyzing
failures.
:param cause: the cause of the exception being raised, when provided this
should itself be an exception instance, this is useful for
creating a chain of exceptions for versions of python where
this is not yet implemented/supported natively.
"""
def __init__(self, message, cause=None):
super(TaskFlowException, self).__init__(message)
@@ -99,7 +107,16 @@ class DependencyFailure(TaskFlowException):
class MissingDependencies(DependencyFailure):
"""Raised when a entity has dependencies that can not be satisfied."""
"""Raised when a entity has dependencies that can not be satisfied.
:param who: the entity that caused the missing dependency to be triggered.
:param requirements: the dependency which were not satisfied.
Further arguments are interpreted as for in
:py:class:`~taskflow.exceptions.TaskFlowException`.
"""
#: Exception message template used when creating an actual message.
MESSAGE_TPL = ("%(who)s requires %(requirements)s but no other entity"
" produces said requirements")
@@ -147,6 +164,9 @@ class WrappedFailure(Exception):
See the failure class documentation for a more comprehensive set of reasons
why this object *may* be reraised instead of the original exception.
:param causes: the :py:class:`~taskflow.utils.misc.Failure` objects that
caused this this exception to be raised.
"""
def __init__(self, causes):
@@ -168,12 +188,14 @@ class WrappedFailure(Exception):
return len(self._causes)
def check(self, *exc_classes):
"""Check if any of exc_classes caused (part of) the failure.
"""Check if any of exception classes caused the failure/s.
Arguments of this method can be exception types or type names
(strings). If any of wrapped failures were caused by exception
of given type, the corresponding argument is returned. Else,
None is returned.
:param exc_classes: exception types/exception type names to
search for.
If any of the contained failures were caused by an exception of a
given type, the corresponding argument that matched is returned. If
not then none is returned.
"""
if not exc_classes:
return None
@@ -189,7 +211,10 @@ class WrappedFailure(Exception):
def exception_message(exc):
"""Return the string representation of exception."""
"""Return the string representation of exception.
:param exc: exception object to get a string representation of.
"""
# NOTE(imelnikov): Dealing with non-ascii data in python is difficult:
# https://bugs.launchpad.net/taskflow/+bug/1275895
# https://bugs.launchpad.net/taskflow/+bug/1276053

View File

@@ -33,43 +33,19 @@ RETRY = "RETRY"
@six.add_metaclass(abc.ABCMeta)
class Decider(object):
"""A class/mixin object that can decide how to resolve execution failures.
A decider may be executed multiple times on subflow or other atom
failure and it is expected to make a decision about what should be done
to resolve the failure (retry, revert to the previous retry, revert
the whole flow, etc.).
"""
@abc.abstractmethod
def on_failure(self, history, *args, **kwargs):
"""On failure makes a decision about the future.
This method will typically use information about prior failures (if
this historical failure information is not available or was not
persisted this history will be empty).
Returns retry action constant:
* ``RETRY`` when subflow must be reverted and restarted again (maybe
with new parameters).
* ``REVERT`` when this subflow must be completely reverted and parent
subflow should make a decision about the flow execution.
* ``REVERT_ALL`` in a case when the whole flow must be reverted and
marked as ``FAILURE``.
"""
@six.add_metaclass(abc.ABCMeta)
class Retry(atom.Atom, Decider):
class Retry(atom.Atom):
"""A class that can decide how to resolve execution failures.
This abstract base class is used to inherit from and provide different
strategies that will be activated upon execution failures. Since a retry
object is an atom it may also provide execute and revert methods to alter
the inputs of connected atoms (depending on the desired strategy to be
used this can be quite useful).
object is an atom it may also provide :meth:`.execute` and
:meth:`.revert` methods to alter the inputs of connected atoms (depending
on the desired strategy to be used this can be quite useful).
NOTE(harlowja): the :meth:`.execute` and :meth:`.revert` and
:meth:`.on_failure` will automatically be given a ``history`` parameter,
which contains information about the past decisions and outcomes
that have occurred (if available).
"""
default_provides = None
@@ -92,11 +68,11 @@ class Retry(atom.Atom, Decider):
@abc.abstractmethod
def execute(self, history, *args, **kwargs):
"""Executes the given retry atom.
"""Executes the given retry.
This execution activates a given retry which will typically produce
data required to start or restart a connected component using
previously provided values and a history of prior failures from
previously provided values and a ``history`` of prior failures from
previous runs. The historical data can be analyzed to alter the
resolution strategy that this retry controller will use.
@@ -105,12 +81,15 @@ class Retry(atom.Atom, Decider):
saved to the history of the retry atom automatically, that is a list of
tuples (result, failures) are persisted where failures is a dictionary
of failures indexed by task names and the result is the execution
result returned by this retry controller during that failure resolution
result returned by this retry during that failure resolution
attempt.
:param args: positional arguments that retry requires to execute.
:param kwargs: any keyword arguments that retry requires to execute.
"""
def revert(self, history, *args, **kwargs):
"""Reverts this retry using the given context.
"""Reverts this retry.
On revert call all results that had been provided by previous tries
and all errors caused during reversion are provided. This method
@@ -118,6 +97,29 @@ class Retry(atom.Atom, Decider):
retry (that is to say that the controller has ran out of resolution
options and has either given up resolution or has failed to handle
a execution failure).
:param args: positional arguments that the retry required to execute.
:param kwargs: any keyword arguments that the retry required to
execute.
"""
@abc.abstractmethod
def on_failure(self, history, *args, **kwargs):
"""Makes a decision about the future.
This method will typically use information about prior failures (if
this historical failure information is not available or was not
persisted the provided history will be empty).
Returns a retry constant (one of):
* ``RETRY``: when the controlling flow must be reverted and restarted
again (for example with new parameters).
* ``REVERT``: when this controlling flow must be completely reverted
and the parent flow (if any) should make a decision about further
flow execution.
* ``REVERT_ALL``: when this controlling flow and the parent
flow (if any) must be reverted and marked as a ``FAILURE``.
"""

View File

@@ -52,7 +52,7 @@ class BaseTask(atom.Atom):
A common pattern for initializing the state of the system prior to
running tasks is to define some code in a base class that all your
tasks inherit from. In that class, you can define a pre_execute
tasks inherit from. In that class, you can define a ``pre_execute``
method and it will always be invoked just prior to your tasks running.
"""
@@ -72,6 +72,9 @@ class BaseTask(atom.Atom):
happens in a different python process or on a remote machine) and so
that the result can be transmitted to other tasks (which may be local
or remote).
:param args: positional arguments that task requires to execute.
:param kwargs: any keyword arguments that task requires to execute.
"""
def post_execute(self):
@@ -79,7 +82,7 @@ class BaseTask(atom.Atom):
A common pattern for cleaning up global state of the system after the
execution of tasks is to define some code in a base class that all your
tasks inherit from. In that class, you can define a post_execute
tasks inherit from. In that class, you can define a ``post_execute``
method and it will always be invoked just after your tasks execute,
regardless of whether they succeded or not.
@@ -90,7 +93,7 @@ class BaseTask(atom.Atom):
def pre_revert(self):
"""Code to be run prior to reverting the task.
This works the same as pre_execute, but for the revert phase.
This works the same as :meth:`.pre_execute`, but for the revert phase.
"""
def revert(self, *args, **kwargs):
@@ -98,26 +101,29 @@ class BaseTask(atom.Atom):
This method should undo any side-effects caused by previous execution
of the task using the result of the :py:meth:`execute` method and
information on failure which triggered reversion of the flow.
information on the failure which triggered reversion of the flow the
task is contained in (if applicable).
NOTE(harlowja): The ``**kwargs`` which are passed into the
:py:meth:`execute` method will also be passed into this method. The
``**kwargs`` key ``'result'`` will contain the :py:meth:`execute`
result (if any) and the ``**kwargs`` key ``'flow_failures'`` will
contain the failure information.
:param args: positional arguments that the task required to execute.
:param kwargs: any keyword arguments that the task required to
execute; the special key ``'result'`` will contain
the :py:meth:`execute` result (if any) and
the ``**kwargs`` key ``'flow_failures'`` will contain
any failure information.
"""
def post_revert(self):
"""Code to be run after reverting the task.
This works the same as post_execute, but for the revert phase.
This works the same as :meth:`.post_execute`, but for the revert phase.
"""
def update_progress(self, progress, **kwargs):
"""Update task progress and notify all registered listeners.
:param progress: task progress float value between 0 and 1
:param kwargs: task specific progress information
:param progress: task progress float value between 0.0 and 1.0
:param kwargs: any keyword arguments that are tied to the specific
progress value.
"""
if progress > 1.0:
LOG.warn("Progress must be <= 1.0, clamping to upper bound")