You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by em...@apache.org on 2017/06/29 00:06:48 UTC

[01/15] incubator-ariatosca git commit: ARIA-284 Cleanup and optimize the task execution [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-286-sphinx-documentation 5be27b0c0 -> 3f09ecdeb (forced update)


ARIA-284 Cleanup and optimize the task execution


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/a75a3dea
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/a75a3dea
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/a75a3dea

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: a75a3dea06741b73b9949e920e28877633a8bc28
Parents: 75112ab
Author: max-orlov <ma...@gigaspaces.com>
Authored: Wed Jun 21 12:41:33 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Sun Jun 25 14:33:23 2017 +0300

----------------------------------------------------------------------
 aria/modeling/orchestration.py                  |   2 -
 aria/orchestrator/context/workflow.py           |  19 ---
 aria/orchestrator/workflow_runner.py            |   7 +-
 aria/orchestrator/workflows/core/compile.py     | 116 ------------------
 aria/orchestrator/workflows/core/engine.py      | 110 ++++++++++-------
 .../workflows/core/graph_compiler.py            | 120 +++++++++++++++++++
 tests/orchestrator/context/__init__.py          |   4 +-
 tests/orchestrator/context/test_serialize.py    |   4 +-
 .../orchestrator/execution_plugin/test_local.py |   4 +-
 tests/orchestrator/execution_plugin/test_ssh.py |   6 +-
 tests/orchestrator/test_workflow_runner.py      |   4 +-
 .../orchestrator/workflows/core/test_engine.py  |   4 +-
 .../orchestrator/workflows/core/test_events.py  |   9 +-
 .../test_task_graph_into_execution_graph.py     |  21 +++-
 .../executor/test_process_executor_extension.py |   4 +-
 .../test_process_executor_tracked_changes.py    |   4 +-
 16 files changed, 229 insertions(+), 209 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 276b68e..5b02d1b 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -306,7 +306,6 @@ class TaskBase(mixins.ModelMixin):
     ended_at = Column(DateTime, default=None)
     attempts_count = Column(Integer, default=1)
 
-    _api_id = Column(String)
     _executor = Column(PickleType)
     _context_cls = Column(PickleType)
     _stub_type = Column(Enum(*STUB_TYPES))
@@ -442,7 +441,6 @@ class TaskBase(mixins.ModelMixin):
                 'plugin': api_task.plugin,
                 'function': api_task.function,
                 'arguments': api_task.arguments,
-                '_api_id': api_task.id,
                 '_context_cls': api_task._context_cls,
                 '_executor': executor,
             }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/orchestrator/context/workflow.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/workflow.py b/aria/orchestrator/context/workflow.py
index adcd635..18334f3 100644
--- a/aria/orchestrator/context/workflow.py
+++ b/aria/orchestrator/context/workflow.py
@@ -20,8 +20,6 @@ Workflow and operation contexts
 import threading
 from contextlib import contextmanager
 
-from networkx import DiGraph
-
 from .exceptions import ContextException
 from .common import BaseContext
 
@@ -96,23 +94,6 @@ class WorkflowContext(BaseContext):
         )
 
     @property
-    def _graph(self):
-        # Constructing a graph with only not ended nodes
-        if self._execution_graph is None:
-            graph = DiGraph()
-            for task in self.execution.tasks:
-                if task.has_ended():
-                    continue
-                for dependency in task.dependencies:
-                    if dependency.has_ended():
-                        continue
-                    graph.add_edge(dependency, task)
-
-            self._execution_graph = graph
-
-        return self._execution_graph
-
-    @property
     @contextmanager
     def persist_changes(self):
         yield

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/orchestrator/workflow_runner.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflow_runner.py b/aria/orchestrator/workflow_runner.py
index 3ccb1ee..4a50fb2 100644
--- a/aria/orchestrator/workflow_runner.py
+++ b/aria/orchestrator/workflow_runner.py
@@ -24,7 +24,7 @@ from datetime import datetime
 from . import exceptions
 from .context.workflow import WorkflowContext
 from .workflows import builtin
-from .workflows.core import engine, compile
+from .workflows.core import engine, graph_compiler
 from .workflows.executor.process import ProcessExecutor
 from ..modeling import models
 from ..modeling import utils as modeling_utils
@@ -96,8 +96,9 @@ class WorkflowRunner(object):
 
         if not self._is_resume:
             workflow_fn = self._get_workflow_fn()
-            tasks_graph = workflow_fn(ctx=self._workflow_context, **execution_inputs_dict)
-            compile.create_execution_tasks(self._workflow_context, tasks_graph, executor.__class__)
+            self._tasks_graph = workflow_fn(ctx=self._workflow_context, **execution_inputs_dict)
+            graph_compiler.GraphCompiler(self._workflow_context, executor.__class__).compile(
+                self._tasks_graph)
 
         self._engine = engine.Engine(executors={executor.__class__: executor})
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/orchestrator/workflows/core/compile.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/compile.py b/aria/orchestrator/workflows/core/compile.py
deleted file mode 100644
index 932268a..0000000
--- a/aria/orchestrator/workflows/core/compile.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from ....modeling import models
-from .. import executor, api
-
-
-def create_execution_tasks(ctx, task_graph, default_executor):
-    execution = ctx.execution
-    _construct_execution_tasks(execution, task_graph, default_executor)
-    ctx.model.execution.update(execution)
-    return execution.tasks
-
-
-def _construct_execution_tasks(execution,
-                               task_graph,
-                               default_executor,
-                               stub_executor=executor.base.StubTaskExecutor,
-                               start_stub_type=models.Task.START_WORKFLOW,
-                               end_stub_type=models.Task.END_WORKFLOW,
-                               depends_on=()):
-    """
-    Translates the user graph to the execution graph
-    :param task_graph: The user's graph
-    :param start_stub_type: internal use
-    :param end_stub_type: internal use
-    :param depends_on: internal use
-    """
-    depends_on = list(depends_on)
-
-    # Insert start marker
-    start_task = models.Task(execution=execution,
-                             dependencies=depends_on,
-                             _api_id=_start_graph_suffix(task_graph.id),
-                             _stub_type=start_stub_type,
-                             _executor=stub_executor)
-
-    for task in task_graph.topological_order(reverse=True):
-        operation_dependencies = _get_tasks_from_dependencies(
-            execution, task_graph.get_dependencies(task), [start_task])
-
-        if isinstance(task, api.task.OperationTask):
-            models.Task.from_api_task(api_task=task,
-                                      executor=default_executor,
-                                      dependencies=operation_dependencies)
-
-        elif isinstance(task, api.task.WorkflowTask):
-            # Build the graph recursively while adding start and end markers
-            _construct_execution_tasks(
-                execution=execution,
-                task_graph=task,
-                default_executor=default_executor,
-                stub_executor=stub_executor,
-                start_stub_type=models.Task.START_SUBWROFKLOW,
-                end_stub_type=models.Task.END_SUBWORKFLOW,
-                depends_on=operation_dependencies
-            )
-        elif isinstance(task, api.task.StubTask):
-            models.Task(execution=execution,
-                        dependencies=operation_dependencies,
-                        _api_id=task.id,
-                        _executor=stub_executor,
-                        _stub_type=models.Task.STUB,
-                       )
-        else:
-            raise RuntimeError('Undefined state')
-
-    # Insert end marker
-    models.Task(dependencies=_get_non_dependent_tasks(execution) or [start_task],
-                execution=execution,
-                _api_id=_end_graph_suffix(task_graph.id),
-                _executor=stub_executor,
-                _stub_type=end_stub_type)
-
-
-def _start_graph_suffix(api_id):
-    return '{0}-Start'.format(api_id)
-
-
-def _end_graph_suffix(api_id):
-    return '{0}-End'.format(api_id)
-
-
-def _get_non_dependent_tasks(execution):
-    tasks_with_dependencies = set()
-    for task in execution.tasks:
-        tasks_with_dependencies.update(task.dependencies)
-    return list(set(execution.tasks) - set(tasks_with_dependencies))
-
-
-def _get_tasks_from_dependencies(execution, dependencies, default=()):
-    """
-    Returns task list from dependencies.
-    """
-    tasks = []
-    for dependency in dependencies:
-        if getattr(dependency, 'actor', False):
-            # This is
-            dependency_name = dependency.id
-        else:
-            dependency_name = _end_graph_suffix(dependency.id)
-        tasks.extend(task for task in execution.tasks if task._api_id == dependency_name)
-    return tasks or default

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/orchestrator/workflows/core/engine.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/engine.py b/aria/orchestrator/workflows/core/engine.py
index d5a6e70..d52ae85 100644
--- a/aria/orchestrator/workflows/core/engine.py
+++ b/aria/orchestrator/workflows/core/engine.py
@@ -45,22 +45,23 @@ class Engine(logger.LoggerMixin):
         """
         execute the workflow
         """
-        executing_tasks = []
-
         if resuming:
             events.on_resume_workflow_signal.send(ctx)
 
+        tasks_tracker = _TasksTracker(ctx)
         try:
             events.start_workflow_signal.send(ctx)
             while True:
                 cancel = self._is_cancel(ctx)
                 if cancel:
                     break
-                for task in self._ended_tasks(ctx, executing_tasks):
-                    self._handle_ended_tasks(ctx, task, executing_tasks)
-                for task in self._executable_tasks(ctx):
-                    self._handle_executable_task(ctx, task, executing_tasks)
-                if self._all_tasks_consumed(ctx):
+                for task in tasks_tracker.ended_tasks:
+                    self._handle_ended_tasks(task)
+                    tasks_tracker.finished(task)
+                for task in tasks_tracker.executable_tasks:
+                    tasks_tracker.executing(task)
+                    self._handle_executable_task(ctx, task)
+                if tasks_tracker.all_tasks_consumed:
                     break
                 else:
                     time.sleep(0.1)
@@ -86,34 +87,7 @@ class Engine(logger.LoggerMixin):
         execution = ctx.model.execution.refresh(ctx.execution)
         return execution.status in (models.Execution.CANCELLING, models.Execution.CANCELLED)
 
-    def _executable_tasks(self, ctx):
-        now = datetime.utcnow()
-        return (
-            task for task in self._tasks_iter(ctx)
-            if task.is_waiting() and task.due_at <= now and \
-            not self._task_has_dependencies(ctx, task)
-        )
-
-    @staticmethod
-    def _ended_tasks(ctx, executing_tasks):
-        for task in executing_tasks:
-            if task.has_ended() and task in ctx._graph:
-                yield task
-
-    @staticmethod
-    def _task_has_dependencies(ctx, task):
-        return len(ctx._graph.pred.get(task, [])) > 0
-
-    @staticmethod
-    def _all_tasks_consumed(ctx):
-        return len(ctx._graph.node) == 0
-
-    @staticmethod
-    def _tasks_iter(ctx):
-        for task in ctx.execution.tasks:
-            yield ctx.model.task.refresh(task)
-
-    def _handle_executable_task(self, ctx, task, executing_tasks):
+    def _handle_executable_task(self, ctx, task):
         task_executor = self._executors[task._executor]
 
         # If the task is a stub, a default context is provided, else it should hold the context cls
@@ -129,16 +103,70 @@ class Engine(logger.LoggerMixin):
             name=task.name
         )
 
-        executing_tasks.append(task)
-
         if not task._stub_type:
             events.sent_task_signal.send(op_ctx)
         task_executor.execute(op_ctx)
 
     @staticmethod
-    def _handle_ended_tasks(ctx, task, executing_tasks):
-        executing_tasks.remove(task)
+    def _handle_ended_tasks(task):
         if task.status == models.Task.FAILED and not task.ignore_failure:
             raise exceptions.ExecutorException('Workflow failed')
-        else:
-            ctx._graph.remove_node(task)
+
+
+class _TasksTracker(object):
+    def __init__(self, ctx):
+        self._ctx = ctx
+        self._tasks = ctx.execution.tasks
+        self._executed_tasks = [task for task in self._tasks if task.has_ended()]
+        self._executable_tasks = list(set(self._tasks) - set(self._executed_tasks))
+        self._executing_tasks = []
+
+    @property
+    def all_tasks_consumed(self):
+        return len(self._executed_tasks) == len(self._tasks) and len(self._executing_tasks) == 0
+
+    def executing(self, task):
+        # Task executing could be retrying (thus removed and added earlier)
+        if task not in self._executing_tasks:
+            self._executable_tasks.remove(task)
+            self._executing_tasks.append(task)
+
+    def finished(self, task):
+        self._executing_tasks.remove(task)
+        self._executed_tasks.append(task)
+
+    @property
+    def ended_tasks(self):
+        for task in self.executing_tasks:
+            if task.has_ended():
+                yield task
+
+    @property
+    def executable_tasks(self):
+        now = datetime.utcnow()
+        # we need both lists since retrying task are in the executing task list.
+        for task in self._update_tasks(self._executing_tasks + self._executable_tasks):
+            if all([task.is_waiting(),
+                    task.due_at <= now,
+                    all(dependency in self._executed_tasks for dependency in task.dependencies)
+                   ]):
+                yield task
+
+    @property
+    def executing_tasks(self):
+        for task in self._update_tasks(self._executing_tasks):
+            yield task
+
+    @property
+    def executed_tasks(self):
+        for task in self._update_tasks(self._executed_tasks):
+            yield task
+
+    @property
+    def tasks(self):
+        for task in self._update_tasks(self._tasks):
+            yield task
+
+    def _update_tasks(self, tasks):
+        for task in tasks:
+            yield self._ctx.model.task.refresh(task)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/aria/orchestrator/workflows/core/graph_compiler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/graph_compiler.py b/aria/orchestrator/workflows/core/graph_compiler.py
new file mode 100644
index 0000000..f339038
--- /dev/null
+++ b/aria/orchestrator/workflows/core/graph_compiler.py
@@ -0,0 +1,120 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from ....modeling import models
+from .. import executor, api
+
+
+class GraphCompiler(object):
+    def __init__(self, ctx, default_executor):
+        self._ctx = ctx
+        self._default_executor = default_executor
+        self._stub_executor = executor.base.StubTaskExecutor
+        self._model_to_api_id = {}
+
+    def compile(self,
+                task_graph,
+                start_stub_type=models.Task.START_WORKFLOW,
+                end_stub_type=models.Task.END_WORKFLOW,
+                depends_on=()):
+        """
+        Translates the user graph to the execution graph
+        :param task_graph: The user's graph
+        :param start_stub_type: internal use
+        :param end_stub_type: internal use
+        :param depends_on: internal use
+        """
+        task_graph = task_graph or self._task_graph
+        depends_on = list(depends_on)
+
+        # Insert start marker
+        start_task = self._create_stub_task(
+            start_stub_type, depends_on, self._start_graph_suffix(task_graph.id), task_graph.name,
+        )
+
+        for task in task_graph.topological_order(reverse=True):
+            dependencies = \
+                (self._get_tasks_from_dependencies(task_graph.get_dependencies(task))
+                 or [start_task])
+
+            if isinstance(task, api.task.OperationTask):
+                self._create_operation_task(task, dependencies)
+
+            elif isinstance(task, api.task.WorkflowTask):
+                # Build the graph recursively while adding start and end markers
+                self.compile(
+                    task, models.Task.START_SUBWROFKLOW, models.Task.END_SUBWORKFLOW, dependencies
+                )
+            elif isinstance(task, api.task.StubTask):
+                self._create_stub_task(models.Task.STUB, dependencies, task.id)
+            else:
+                raise RuntimeError('Undefined state')
+
+        # Insert end marker
+        self._create_stub_task(
+            end_stub_type,
+            self._get_non_dependent_tasks(self._ctx.execution) or [start_task],
+            self._end_graph_suffix(task_graph.id),
+            task_graph.name
+        )
+
+    def _create_stub_task(self, stub_type, dependencies, api_id, name=None):
+        model_task = models.Task(
+            name=name,
+            dependencies=dependencies,
+            execution=self._ctx.execution,
+            _executor=self._stub_executor,
+            _stub_type=stub_type)
+        self._ctx.model.task.put(model_task)
+        self._model_to_api_id[model_task.id] = api_id
+        return model_task
+
+    def _create_operation_task(self, api_task, dependencies):
+        model_task = models.Task.from_api_task(
+            api_task, self._default_executor, dependencies=dependencies)
+        self._ctx.model.task.put(model_task)
+        self._model_to_api_id[model_task.id] = api_task.id
+        return model_task
+
+    @staticmethod
+    def _start_graph_suffix(api_id):
+        return '{0}-Start'.format(api_id)
+
+    @staticmethod
+    def _end_graph_suffix(api_id):
+        return '{0}-End'.format(api_id)
+
+    @staticmethod
+    def _get_non_dependent_tasks(execution):
+        tasks_with_dependencies = set()
+        for task in execution.tasks:
+            tasks_with_dependencies.update(task.dependencies)
+        return list(set(execution.tasks) - set(tasks_with_dependencies))
+
+    def _get_tasks_from_dependencies(self, dependencies):
+        """
+        Returns task list from dependencies.
+        """
+        tasks = []
+        for dependency in dependencies:
+            if getattr(dependency, 'actor', False):
+                # This is
+                dependency_name = dependency.id
+            else:
+                dependency_name = self._end_graph_suffix(dependency.id)
+            tasks.extend(task for task in self._ctx.execution.tasks
+                         if self._model_to_api_id.get(task.id, None) == dependency_name)
+        return tasks

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/context/__init__.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/__init__.py b/tests/orchestrator/context/__init__.py
index 086a066..780db07 100644
--- a/tests/orchestrator/context/__init__.py
+++ b/tests/orchestrator/context/__init__.py
@@ -15,7 +15,7 @@
 
 import sys
 
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 
 
 def op_path(func, module_path=None):
@@ -26,7 +26,7 @@ def op_path(func, module_path=None):
 def execute(workflow_func, workflow_context, executor):
     graph = workflow_func(ctx=workflow_context)
 
-    compile.create_execution_tasks(workflow_context, graph, executor.__class__)
+    graph_compiler.GraphCompiler(workflow_context, executor.__class__).compile(graph)
     eng = engine.Engine(executors={executor.__class__: executor})
 
     eng.execute(workflow_context)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/context/test_serialize.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_serialize.py b/tests/orchestrator/context/test_serialize.py
index 5db5b63..6046a16 100644
--- a/tests/orchestrator/context/test_serialize.py
+++ b/tests/orchestrator/context/test_serialize.py
@@ -16,7 +16,7 @@
 import pytest
 
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor import process
 from aria.orchestrator import workflow, operation
 import tests
@@ -48,7 +48,7 @@ def test_serialize_operation_context(context, executor, tmpdir):
     context.model.node.update(node)
 
     graph = _mock_workflow(ctx=context)  # pylint: disable=no-value-for-parameter
-    compile.create_execution_tasks(context, graph, executor.__class__)
+    graph_compiler.GraphCompiler(context, executor.__class__).compile(graph)
     eng = engine.Engine({executor.__class__: executor})
     eng.execute(context)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/execution_plugin/test_local.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_local.py b/tests/orchestrator/execution_plugin/test_local.py
index 1695320..5b94917 100644
--- a/tests/orchestrator/execution_plugin/test_local.py
+++ b/tests/orchestrator/execution_plugin/test_local.py
@@ -28,7 +28,7 @@ from aria.orchestrator.execution_plugin.exceptions import ProcessException
 from aria.orchestrator.execution_plugin import local
 from aria.orchestrator.execution_plugin import constants
 from aria.orchestrator.workflows.executor import process
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 
 from tests import mock
 from tests import storage
@@ -500,7 +500,7 @@ if __name__ == '__main__':
                 arguments=arguments))
             return graph
         tasks_graph = mock_workflow(ctx=workflow_context)  # pylint: disable=no-value-for-parameter
-        compile.create_execution_tasks(workflow_context, tasks_graph, executor.__class__)
+        graph_compiler.GraphCompiler(workflow_context, executor.__class__).compile(tasks_graph)
         eng = engine.Engine({executor.__class__: executor})
         eng.execute(workflow_context)
         return workflow_context.model.node.get_by_name(

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/execution_plugin/test_ssh.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_ssh.py b/tests/orchestrator/execution_plugin/test_ssh.py
index fb1dc09..4fa8184 100644
--- a/tests/orchestrator/execution_plugin/test_ssh.py
+++ b/tests/orchestrator/execution_plugin/test_ssh.py
@@ -29,7 +29,7 @@ from aria.orchestrator import events
 from aria.orchestrator import workflow
 from aria.orchestrator.workflows import api
 from aria.orchestrator.workflows.executor import process
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.exceptions import ExecutorException
 from aria.orchestrator.exceptions import TaskAbortException, TaskRetryException
 from aria.orchestrator.execution_plugin import operations
@@ -254,8 +254,8 @@ class TestWithActualSSHServer(object):
             graph.sequence(*ops)
             return graph
         tasks_graph = mock_workflow(ctx=self._workflow_context)  # pylint: disable=no-value-for-parameter
-        compile.create_execution_tasks(
-            self._workflow_context, tasks_graph, self._executor.__class__)
+        graph_compiler.GraphCompiler(
+            self._workflow_context, self._executor.__class__).compile(tasks_graph)
         eng = engine.Engine({self._executor.__class__: self._executor})
         eng.execute(self._workflow_context)
         return self._workflow_context.model.node.get_by_name(

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/test_workflow_runner.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/test_workflow_runner.py b/tests/orchestrator/test_workflow_runner.py
index ae82476..103596b 100644
--- a/tests/orchestrator/test_workflow_runner.py
+++ b/tests/orchestrator/test_workflow_runner.py
@@ -27,7 +27,7 @@ from aria.orchestrator.events import on_cancelled_workflow_signal
 from aria.orchestrator.workflow_runner import WorkflowRunner
 from aria.orchestrator.workflows.executor.process import ProcessExecutor
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor import thread
 from aria.orchestrator import (
     workflow,
@@ -410,7 +410,7 @@ class TestResumableWorkflows(object):
     def _engine(workflow_func, workflow_context, executor):
         graph = workflow_func(ctx=workflow_context)
         execution = workflow_context.execution
-        compile.create_execution_tasks(execution, graph, executor.__class__)
+        graph_compiler.GraphCompiler(workflow_context, executor.__class__).compile(graph)
         workflow_context.execution = execution
 
         return engine.Engine(executors={executor.__class__: executor})

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/workflows/core/test_engine.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_engine.py b/tests/orchestrator/workflows/core/test_engine.py
index b77d284..21a53d7 100644
--- a/tests/orchestrator/workflows/core/test_engine.py
+++ b/tests/orchestrator/workflows/core/test_engine.py
@@ -28,7 +28,7 @@ from aria.orchestrator.workflows import (
     api,
     exceptions,
 )
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor import thread
 
 from tests import mock, storage
@@ -50,7 +50,7 @@ class BaseTest(object):
     @staticmethod
     def _engine(workflow_func, workflow_context, executor):
         graph = workflow_func(ctx=workflow_context)
-        compile.create_execution_tasks(workflow_context, graph, executor.__class__)
+        graph_compiler.GraphCompiler(workflow_context, executor.__class__).compile(graph)
 
         return engine.Engine(executors={executor.__class__: executor})
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/workflows/core/test_events.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_events.py b/tests/orchestrator/workflows/core/test_events.py
index 2b82443..30cc8ee 100644
--- a/tests/orchestrator/workflows/core/test_events.py
+++ b/tests/orchestrator/workflows/core/test_events.py
@@ -16,7 +16,7 @@
 import pytest
 
 from aria.orchestrator.decorators import operation, workflow
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor.thread import ThreadExecutor
 from aria.orchestrator.workflows import api
 from aria.modeling.service_instance import NodeBase
@@ -113,10 +113,9 @@ def run_operation_on_node(ctx, op_name, interface_name):
         operation_name=op_name,
         operation_kwargs=dict(function='{name}.{func.__name__}'.format(name=__name__, func=func)))
     node.interfaces[interface.name] = interface
-    compile.create_execution_tasks(
-        ctx,
-        single_operation_workflow(ctx, node=node, interface_name=interface_name, op_name=op_name),
-        ThreadExecutor)
+    graph_compiler.GraphCompiler(ctx, ThreadExecutor).compile(
+        single_operation_workflow(ctx, node=node, interface_name=interface_name, op_name=op_name)
+    )
 
     eng = engine.Engine(executors={ThreadExecutor: ThreadExecutor()})
     eng.execute(ctx)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
index f5fb17a..f0d2b26 100644
--- a/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
+++ b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
@@ -13,12 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from networkx import topological_sort
+from networkx import topological_sort, DiGraph
 
 from aria.modeling import models
 from aria.orchestrator import context
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.core import compile
+from aria.orchestrator.workflows.core import graph_compiler
 from aria.orchestrator.workflows.executor import base
 from tests import mock
 from tests import storage
@@ -65,9 +65,10 @@ def test_task_graph_into_execution_graph(tmpdir):
     test_task_graph.add_dependency(inner_task_graph, simple_before_task)
     test_task_graph.add_dependency(simple_after_task, inner_task_graph)
 
-    compile.create_execution_tasks(workflow_context, test_task_graph, base.StubTaskExecutor)
+    compiler = graph_compiler.GraphCompiler(workflow_context, base.StubTaskExecutor)
+    compiler.compile(test_task_graph)
 
-    execution_tasks = topological_sort(workflow_context._graph)
+    execution_tasks = topological_sort(_graph(workflow_context.execution.tasks))
 
     assert len(execution_tasks) == 7
 
@@ -81,7 +82,7 @@ def test_task_graph_into_execution_graph(tmpdir):
         '{0}-End'.format(test_task_graph.id)
     ]
 
-    assert expected_tasks_names == [t._api_id for t in execution_tasks]
+    assert expected_tasks_names == [compiler._model_to_api_id[t.id] for t in execution_tasks]
     assert all(isinstance(task, models.Task) for task in execution_tasks)
     execution_tasks = iter(execution_tasks)
 
@@ -97,7 +98,6 @@ def test_task_graph_into_execution_graph(tmpdir):
 
 
 def _assert_execution_is_api_task(execution_task, api_task):
-    assert execution_task._api_id == api_task.id
     assert execution_task.name == api_task.name
     assert execution_task.function == api_task.function
     assert execution_task.actor == api_task.actor
@@ -106,3 +106,12 @@ def _assert_execution_is_api_task(execution_task, api_task):
 
 def _get_task_by_name(task_name, graph):
     return graph.node[task_name]['task']
+
+
+def _graph(tasks):
+    graph = DiGraph()
+    for task in tasks:
+        for dependency in task.dependencies:
+            graph.add_edge(dependency, task)
+
+    return graph

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/workflows/executor/test_process_executor_extension.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor_extension.py b/tests/orchestrator/workflows/executor/test_process_executor_extension.py
index ba98c4f..6ed3e2b 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor_extension.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor_extension.py
@@ -17,7 +17,7 @@ import pytest
 
 from aria import extension
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor import process
 from aria.orchestrator import workflow, operation
 
@@ -57,7 +57,7 @@ def test_decorate_extension(context, executor):
         graph.add_tasks(task)
         return graph
     graph = mock_workflow(ctx=context)  # pylint: disable=no-value-for-parameter
-    compile.create_execution_tasks(context, graph, executor.__class__)
+    graph_compiler.GraphCompiler(context, executor.__class__).compile(graph)
     eng = engine.Engine({executor.__class__: executor})
     eng.execute(context)
     out = get_node(context).attributes.get('out').value

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a75a3dea/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py b/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py
index 2f1c325..a74a473 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor_tracked_changes.py
@@ -18,7 +18,7 @@ import copy
 import pytest
 
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.core import engine, compile
+from aria.orchestrator.workflows.core import engine, graph_compiler
 from aria.orchestrator.workflows.executor import process
 from aria.orchestrator import workflow, operation
 from aria.orchestrator.workflows import exceptions
@@ -107,7 +107,7 @@ def _run_workflow(context, executor, op_func, arguments=None):
         graph.add_tasks(task)
         return graph
     graph = mock_workflow(ctx=context)  # pylint: disable=no-value-for-parameter
-    compile.create_execution_tasks(context, graph, executor.__class__)
+    graph_compiler.GraphCompiler(context, executor.__class__).compile(graph)
     eng = engine.Engine({executor.__class__: executor})
     eng.execute(context)
     out = context.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME).attributes.get('out')


[06/15] incubator-ariatosca git commit: ARIA-294 Workflow tasks execution is not in order

Posted by em...@apache.org.
ARIA-294 Workflow tasks execution is not in order


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/b1b1ee44
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/b1b1ee44
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/b1b1ee44

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: b1b1ee4457dce0b851277e5289faa2178f638f48
Parents: 7bba3ab
Author: max-orlov <ma...@gigaspaces.com>
Authored: Tue Jun 27 20:32:08 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Wed Jun 28 12:12:12 2017 +0300

----------------------------------------------------------------------
 aria/modeling/orchestration.py                  |   7 +-
 aria/modeling/relationship.py                   | 111 ++++++++-----------
 aria/modeling/service_common.py                 |   2 +-
 aria/modeling/service_instance.py               |   4 +-
 aria/modeling/service_template.py               |   2 +-
 aria/orchestrator/workflow_runner.py            |   4 +-
 .../workflows/core/graph_compiler.py            |   4 +-
 tests/orchestrator/test_workflow_runner.py      |  10 +-
 .../test_task_graph_into_execution_graph.py     |  89 ++++++++++++---
 .../workflows/executor/test_process_executor.py |   2 +-
 10 files changed, 134 insertions(+), 101 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 5b02d1b..829c305 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -397,13 +397,8 @@ class TaskBase(mixins.ModelMixin):
         raise TaskRetryException(message, retry_interval=retry_interval)
 
     @declared_attr
-    def dependency_fk(self):
-        return relationship.foreign_key('task', nullable=True)
-
-    @declared_attr
     def dependencies(cls):
-        # symmetric relationship causes funky graphs
-        return relationship.one_to_many_self(cls, 'dependency_fk')
+        return relationship.many_to_many(cls, self=True)
 
     def has_ended(self):
         return self.status in (self.SUCCESS, self.FAILED)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index 40be5b2..76ac316 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -90,35 +90,6 @@ def one_to_one_self(model_class, fk):
     )
 
 
-def one_to_many_self(model_class, fk, dict_key=None):
-    """
-    Declare a one-to-many relationship property. The property value would be a list or dict of
-    instances of the same model.
-
-    You will need an associated foreign key to our own table.
-
-    *This utility method should only be used during class creation.*
-
-    :param model_class: The class in which this relationship will be declared
-    :type model_class: type
-    :param fk: Foreign key name
-    :type fk: basestring
-    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
-                     be a list
-    :type dict_key: basestring
-    """
-    return _relationship(
-        model_class,
-        model_class.__tablename__,
-        relationship_kwargs={
-            'remote_side': '{model_class}.{remote_column}'.format(
-                model_class=model_class.__name__, remote_column=fk)
-        },
-        back_populates=False,
-        dict_key=dict_key
-    )
-
-
 def one_to_one(model_class,
                other_table,
                fk=None,
@@ -162,11 +133,12 @@ def one_to_one(model_class,
 
 
 def one_to_many(model_class,
-                child_table,
-                child_fk=None,
+                other_table=None,
+                other_fk=None,
                 dict_key=None,
                 back_populates=None,
-                rel_kwargs=None):
+                rel_kwargs=None,
+                self=False):
     """
     Declare a one-to-many relationship property. The property value would be a list or dict of
     instances of the child table's model.
@@ -181,9 +153,9 @@ def one_to_many(model_class,
     :param model_class: The class in which this relationship will be declared
     :type model_class: type
     :param child_table: Child table name
-    :type child_table: basestring
-    :param child_fk: Foreign key name at the child table (no need specify if there's no ambiguity)
-    :type child_fk: basestring
+    :type other_table: basestring
+    :param other_fk: Foreign key name at the child table (no need specify if there's no ambiguity)
+    :type other_fk: basestring
     :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
                      be a list
     :type dict_key: basestring
@@ -191,18 +163,28 @@ def one_to_many(model_class,
                            false to disable
     :type back_populates: basestring|bool
     """
-    rel_kwargs = rel_kwargs or {}
-    rel_kwargs.setdefault('cascade', 'all')
-    if back_populates is None:
-        back_populates = model_class.__tablename__
+    relationship_kwargs = rel_kwargs or {}
+    if self:
+        assert other_fk
+        other_table_name = model_class.__tablename__
+        back_populates = False
+        relationship_kwargs['remote_side'] = '{model}.{column}'.format(model=model_class.__name__,
+                                                                       column=other_fk)
+
+    else:
+        assert other_table
+        other_table_name = other_table
+        if back_populates is None:
+            back_populates = model_class.__tablename__
+        relationship_kwargs.setdefault('cascade', 'all')
 
     return _relationship(
         model_class,
-        child_table,
+        other_table_name,
         back_populates=back_populates,
-        other_fk=child_fk,
+        other_fk=other_fk,
         dict_key=dict_key,
-        relationship_kwargs=rel_kwargs)
+        relationship_kwargs=relationship_kwargs)
 
 
 def many_to_one(model_class,
@@ -244,10 +226,11 @@ def many_to_one(model_class,
 
 
 def many_to_many(model_class,
-                 other_table,
+                 other_table=None,
                  prefix=None,
                  dict_key=None,
-                 other_property=None):
+                 other_property=None,
+                 self=False):
     """
     Declare a many-to-many relationship property. The property value would be a list or dict of
     instances of the other table's model.
@@ -280,8 +263,11 @@ def many_to_many(model_class,
     this_column_name = '{0}_id'.format(this_table)
     this_foreign_key = '{0}.id'.format(this_table)
 
-    other_column_name = '{0}_id'.format(other_table)
-    other_foreign_key = '{0}.id'.format(other_table)
+    if self:
+        other_table = this_table
+
+    other_column_name = '{0}_{1}'.format(other_table, 'self_ref_id' if self else 'id')
+    other_foreign_key = '{0}.{1}'.format(other_table, 'id')
 
     secondary_table_name = '{0}_{1}'.format(this_table, other_table)
 
@@ -299,13 +285,20 @@ def many_to_many(model_class,
         other_foreign_key
     )
 
-    return _relationship(
-        model_class,
-        other_table,
-        relationship_kwargs={'secondary': secondary_table},
-        backref_kwargs={'name': other_property, 'uselist': True} if other_property else None,
-        dict_key=dict_key
-    )
+    kwargs = {'relationship_kwargs': {'secondary': secondary_table}}
+
+    if self:
+        kwargs['back_populates'] = NO_BACK_POP
+        kwargs['relationship_kwargs']['primaryjoin'] = \
+                    getattr(model_class, 'id') == getattr(secondary_table.c, this_column_name)
+        kwargs['relationship_kwargs']['secondaryjoin'] = \
+            getattr(model_class, 'id') == getattr(secondary_table.c, other_column_name)
+    else:
+        kwargs['backref_kwargs'] = \
+            {'name': other_property, 'uselist': True} if other_property else None
+        kwargs['dict_key'] = dict_key
+
+    return _relationship(model_class, other_table, **kwargs)
 
 
 def _relationship(model_class,
@@ -368,14 +361,6 @@ def _get_secondary_table(metadata,
     return Table(
         name,
         metadata,
-        Column(
-            first_column,
-            Integer,
-            ForeignKey(first_foreign_key)
-        ),
-        Column(
-            second_column,
-            Integer,
-            ForeignKey(second_foreign_key)
-        )
+        Column(first_column, Integer, ForeignKey(first_foreign_key)),
+        Column(second_column, Integer, ForeignKey(second_foreign_key))
     )

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 272dfd7..0bb861f 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -320,7 +320,7 @@ class TypeBase(InstanceModelMixin):
 
     @declared_attr
     def children(cls):
-        return relationship.one_to_many_self(cls, 'parent_type_fk')
+        return relationship.one_to_many(cls, other_fk='parent_type_fk', self=True)
 
     # region foreign keys
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index 2bf9872..b451889 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -483,7 +483,7 @@ class NodeBase(InstanceModelMixin):
     @declared_attr
     def outbound_relationships(cls):
         return relationship.one_to_many(
-            cls, 'relationship', child_fk='source_node_fk', back_populates='source_node',
+            cls, 'relationship', other_fk='source_node_fk', back_populates='source_node',
             rel_kwargs=dict(
                 order_by='Relationship.source_position',
                 collection_class=ordering_list('source_position', count_from=0)
@@ -493,7 +493,7 @@ class NodeBase(InstanceModelMixin):
     @declared_attr
     def inbound_relationships(cls):
         return relationship.one_to_many(
-            cls, 'relationship', child_fk='target_node_fk', back_populates='target_node',
+            cls, 'relationship', other_fk='target_node_fk', back_populates='target_node',
             rel_kwargs=dict(
                 order_by='Relationship.target_position',
                 collection_class=ordering_list('target_position', count_from=0)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 4d1e837..344da6d 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -493,7 +493,7 @@ class NodeTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def requirement_templates(cls):
-        return relationship.one_to_many(cls, 'requirement_template', child_fk='node_template_fk')
+        return relationship.one_to_many(cls, 'requirement_template', other_fk='node_template_fk')
 
     @declared_attr
     def properties(cls):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/orchestrator/workflow_runner.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflow_runner.py b/aria/orchestrator/workflow_runner.py
index 4a50fb2..3d58386 100644
--- a/aria/orchestrator/workflow_runner.py
+++ b/aria/orchestrator/workflow_runner.py
@@ -97,8 +97,8 @@ class WorkflowRunner(object):
         if not self._is_resume:
             workflow_fn = self._get_workflow_fn()
             self._tasks_graph = workflow_fn(ctx=self._workflow_context, **execution_inputs_dict)
-            graph_compiler.GraphCompiler(self._workflow_context, executor.__class__).compile(
-                self._tasks_graph)
+            compiler = graph_compiler.GraphCompiler(self._workflow_context, executor.__class__)
+            compiler.compile(self._tasks_graph)
 
         self._engine = engine.Engine(executors={executor.__class__: executor})
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/aria/orchestrator/workflows/core/graph_compiler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/graph_compiler.py b/aria/orchestrator/workflows/core/graph_compiler.py
index f339038..81543d5 100644
--- a/aria/orchestrator/workflows/core/graph_compiler.py
+++ b/aria/orchestrator/workflows/core/graph_compiler.py
@@ -37,7 +37,6 @@ class GraphCompiler(object):
         :param end_stub_type: internal use
         :param depends_on: internal use
         """
-        task_graph = task_graph or self._task_graph
         depends_on = list(depends_on)
 
         # Insert start marker
@@ -110,8 +109,7 @@ class GraphCompiler(object):
         """
         tasks = []
         for dependency in dependencies:
-            if getattr(dependency, 'actor', False):
-                # This is
+            if isinstance(dependency, (api.task.StubTask, api.task.OperationTask)):
                 dependency_name = dependency.id
             else:
                 dependency_name = self._end_graph_suffix(dependency.id)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/tests/orchestrator/test_workflow_runner.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/test_workflow_runner.py b/tests/orchestrator/test_workflow_runner.py
index 103596b..e640c7d 100644
--- a/tests/orchestrator/test_workflow_runner.py
+++ b/tests/orchestrator/test_workflow_runner.py
@@ -350,11 +350,11 @@ class TestResumableWorkflows(object):
         if events['execution_ended'].wait(60) is False:
             raise TimeoutError("Execution did not end")
 
-        first_task, second_task = workflow_context.model.task.list(filters={'_stub_type': None})
-        assert first_task.status == first_task.SUCCESS
-        assert second_task.status in (second_task.FAILED, second_task.RETRYING)
+        tasks = workflow_context.model.task.list(filters={'_stub_type': None})
+        assert any(task.status == task.SUCCESS for task in tasks)
+        assert any(task.status in (task.FAILED, task.RETRYING) for task in tasks)
         events['is_resumed'].set()
-        assert second_task.status in (second_task.FAILED, second_task.RETRYING)
+        assert any(task.status in (task.FAILED, task.RETRYING) for task in tasks)
 
         # Create a new workflow runner, with an existing execution id. This would cause
         # the old execution to restart.
@@ -370,7 +370,7 @@ class TestResumableWorkflows(object):
         new_wf_runner.execute()
 
         # Wait for it to finish and assert changes.
-        assert second_task.status == second_task.SUCCESS
+        assert all(task.status == task.SUCCESS for task in tasks)
         assert node.attributes['invocations'].value == 3
         assert wf_runner.execution.status == wf_runner.execution.SUCCEEDED
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
index f0d2b26..e24c901 100644
--- a/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
+++ b/tests/orchestrator/workflows/core/test_task_graph_into_execution_graph.py
@@ -26,15 +26,17 @@ from tests import storage
 
 def test_task_graph_into_execution_graph(tmpdir):
     interface_name = 'Standard'
-    operation_name = 'create'
+    op1_name, op2_name, op3_name = 'create', 'configure', 'start'
     workflow_context = mock.context.simple(str(tmpdir))
     node = workflow_context.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
     interface = mock.models.create_interface(
         node.service,
         interface_name,
-        operation_name,
+        op1_name,
         operation_kwargs=dict(function='test')
     )
+    interface.operations[op2_name] = mock.models.create_operation(op2_name)                         # pylint: disable=unsubscriptable-object
+    interface.operations[op3_name] = mock.models.create_operation(op3_name)                         # pylint: disable=unsubscriptable-object
     node.interfaces[interface.name] = interface
     workflow_context.model.node.update(node)
 
@@ -46,18 +48,31 @@ def test_task_graph_into_execution_graph(tmpdir):
         simple_before_task = api.task.OperationTask(
             node,
             interface_name=interface_name,
-            operation_name=operation_name)
+            operation_name=op1_name)
         simple_after_task = api.task.OperationTask(
             node,
             interface_name=interface_name,
-            operation_name=operation_name)
+            operation_name=op1_name)
 
         inner_task_graph = api.task.WorkflowTask(sub_workflow, name='test_inner_task_graph')
-        inner_task = api.task.OperationTask(
+        inner_task_1 = api.task.OperationTask(
             node,
             interface_name=interface_name,
-            operation_name=operation_name)
-        inner_task_graph.add_tasks(inner_task)
+            operation_name=op1_name)
+        inner_task_2 = api.task.OperationTask(
+            node,
+            interface_name=interface_name,
+            operation_name=op2_name)
+        inner_task_3 = api.task.OperationTask(
+            node,
+            interface_name=interface_name,
+            operation_name=op3_name)
+        inner_task_graph.add_tasks(inner_task_1)
+        inner_task_graph.add_tasks(inner_task_2)
+        inner_task_graph.add_tasks(inner_task_3)
+        inner_task_graph.add_dependency(inner_task_2, inner_task_1)
+        inner_task_graph.add_dependency(inner_task_3, inner_task_1)
+        inner_task_graph.add_dependency(inner_task_3, inner_task_2)
 
     test_task_graph.add_tasks(simple_before_task)
     test_task_graph.add_tasks(simple_after_task)
@@ -70,13 +85,15 @@ def test_task_graph_into_execution_graph(tmpdir):
 
     execution_tasks = topological_sort(_graph(workflow_context.execution.tasks))
 
-    assert len(execution_tasks) == 7
+    assert len(execution_tasks) == 9
 
     expected_tasks_names = [
         '{0}-Start'.format(test_task_graph.id),
         simple_before_task.id,
         '{0}-Start'.format(inner_task_graph.id),
-        inner_task.id,
+        inner_task_1.id,
+        inner_task_2.id,
+        inner_task_3.id,
         '{0}-End'.format(inner_task_graph.id),
         simple_after_task.id,
         '{0}-End'.format(test_task_graph.id)
@@ -86,17 +103,55 @@ def test_task_graph_into_execution_graph(tmpdir):
     assert all(isinstance(task, models.Task) for task in execution_tasks)
     execution_tasks = iter(execution_tasks)
 
-    assert next(execution_tasks)._stub_type == models.Task.START_WORKFLOW
-    _assert_execution_is_api_task(next(execution_tasks), simple_before_task)
-    assert next(execution_tasks)._stub_type == models.Task.START_SUBWROFKLOW
-    _assert_execution_is_api_task(next(execution_tasks), inner_task)
-    assert next(execution_tasks)._stub_type == models.Task.END_SUBWORKFLOW
-    _assert_execution_is_api_task(next(execution_tasks), simple_after_task)
-    assert next(execution_tasks)._stub_type == models.Task.END_WORKFLOW
-
+    _assert_tasks(
+        iter(execution_tasks),
+        iter([simple_after_task, inner_task_1, inner_task_2, inner_task_3, simple_after_task])
+    )
     storage.release_sqlite_storage(workflow_context.model)
 
 
+def _assert_tasks(execution_tasks, api_tasks):
+    start_workflow_exec_task = next(execution_tasks)
+    assert start_workflow_exec_task._stub_type == models.Task.START_WORKFLOW
+
+    before_exec_task = next(execution_tasks)
+    simple_before_task = next(api_tasks)
+    _assert_execution_is_api_task(before_exec_task, simple_before_task)
+    assert before_exec_task.dependencies == [start_workflow_exec_task]
+
+    start_subworkflow_exec_task = next(execution_tasks)
+    assert start_subworkflow_exec_task._stub_type == models.Task.START_SUBWROFKLOW
+    assert start_subworkflow_exec_task.dependencies == [before_exec_task]
+
+    inner_exec_task_1 = next(execution_tasks)
+    inner_task_1 = next(api_tasks)
+    _assert_execution_is_api_task(inner_exec_task_1, inner_task_1)
+    assert inner_exec_task_1.dependencies == [start_subworkflow_exec_task]
+
+    inner_exec_task_2 = next(execution_tasks)
+    inner_task_2 = next(api_tasks)
+    _assert_execution_is_api_task(inner_exec_task_2, inner_task_2)
+    assert inner_exec_task_2.dependencies == [inner_exec_task_1]
+
+    inner_exec_task_3 = next(execution_tasks)
+    inner_task_3 = next(api_tasks)
+    _assert_execution_is_api_task(inner_exec_task_3, inner_task_3)
+    assert sorted(inner_exec_task_3.dependencies) == sorted([inner_exec_task_1, inner_exec_task_2])
+
+    end_subworkflow_exec_task = next(execution_tasks)
+    assert end_subworkflow_exec_task._stub_type == models.Task.END_SUBWORKFLOW
+    assert end_subworkflow_exec_task.dependencies == [inner_exec_task_3]
+
+    after_exec_task = next(execution_tasks)
+    simple_after_task = next(api_tasks)
+    _assert_execution_is_api_task(after_exec_task, simple_after_task)
+    assert after_exec_task.dependencies == [end_subworkflow_exec_task]
+
+    end_workflow_exec_task = next(execution_tasks)
+    assert end_workflow_exec_task._stub_type == models.Task.END_WORKFLOW
+    assert end_workflow_exec_task.dependencies == [after_exec_task]
+
+
 def _assert_execution_is_api_task(execution_task, api_task):
     assert execution_task.name == api_task.name
     assert execution_task.function == api_task.function

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b1b1ee44/tests/orchestrator/workflows/executor/test_process_executor.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor.py b/tests/orchestrator/workflows/executor/test_process_executor.py
index 6f5c827..6cac288 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor.py
@@ -99,7 +99,7 @@ class TestProcessExecutor(object):
         executor.terminate(ctx.task.id)
 
         # Give a chance to the processes to terminate
-        time.sleep(2)
+        time.sleep(10) # windows might require more time
         assert not any(p.pid == pid and p.status() != psutil.STATUS_ZOMBIE
                        for p in psutil.process_iter()
                        for pid in pids)


[13/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index b451889..002a87c 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+ARIA modeling service instance module
+"""
+
 # pylint: disable=too-many-lines, no-self-argument, no-member, abstract-method
 
 from sqlalchemy import (
@@ -23,7 +27,6 @@ from sqlalchemy import (
     Boolean
 )
 from sqlalchemy import DateTime
-from sqlalchemy.ext.associationproxy import association_proxy
 from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.ext.orderinglist import ordering_list
 
@@ -45,72 +48,21 @@ from . import (
 
 class ServiceBase(InstanceModelMixin):
     """
-    A service is usually an instance of a :class:`ServiceTemplate`.
-
-    You will usually not create it programmatically, but instead instantiate it from a service
-    template.
-
-    :ivar name: Name (unique for this ARIA installation)
-    :vartype name: basestring
-    :ivar service_template: Template from which this service was instantiated (optional)
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar meta_data: Custom annotations
-    :vartype meta_data: {basestring: :class:`Metadata`}
-    :ivar node: Nodes
-    :vartype node: {basestring: :class:`Node`}
-    :ivar groups: Groups of nodes
-    :vartype groups: {basestring: :class:`Group`}
-    :ivar policies: Policies
-    :vartype policies: {basestring: :class:`Policy`]}
-    :ivar substitution: The entire service can appear as a node
-    :vartype substitution: :class:`Substitution`
-    :ivar inputs: Externally provided parameters
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar outputs: These parameters are filled in after service installation
-    :vartype outputs: {basestring: :class:`Output`}
-    :ivar workflows: Custom workflows that can be performed on the service
-    :vartype workflows: {basestring: :class:`Operation`}
-    :ivar plugins: Plugins used by the service
-    :vartype plugins: {basestring: :class:`Plugin`}
-    :ivar created_at: Creation timestamp
-    :vartype created_at: :class:`datetime.datetime`
-    :ivar updated_at: Update timestamp
-    :vartype updated_at: :class:`datetime.datetime`
-    :ivar modifications: Modifications of this service
-    :vartype modifications: [:class:`ServiceModification`]
-    :ivar updates: Updates of this service
-    :vartype updates: [:class:`ServiceUpdate`]
-    :ivar executions: Executions on this service
-    :vartype executions: [:class:`Execution`]
+    Usually an instance of a :class:`ServiceTemplate` and its many associated templates (node
+    templates, group templates, policy templates, etc.). However, it can also be created
+    programmatically.
     """
 
     __tablename__ = 'service'
 
-    __private_fields__ = ['substitution_fk',
-                          'service_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def substitution_fk(cls):
-        """Service one-to-one to Substitution"""
-        return relationship.foreign_key('substitution', nullable=True)
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For Service many-to-one to ServiceTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    # endregion
+    __private_fields__ = ('substitution_fk',
+                          'service_template_fk')
 
     # region association proxies
 
     @declared_attr
     def service_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service_template', 'name')
+        return relationship.association_proxy('service_template', 'name', type=':obj:`basestring`')
 
     # endregion
 
@@ -118,6 +70,11 @@ class ServiceBase(InstanceModelMixin):
 
     @declared_attr
     def substitution(cls):
+        """
+        Exposes the entire service as a single node.
+
+        :type: :class:`Substitution`
+        """
         return relationship.one_to_one(cls, 'substitution', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -126,38 +83,83 @@ class ServiceBase(InstanceModelMixin):
 
     @declared_attr
     def outputs(cls):
+        """
+        Output parameters.
+
+        :type: {:obj:`basestring`: :class:`Output`}
+        """
         return relationship.one_to_many(cls, 'output', dict_key='name')
 
     @declared_attr
     def inputs(cls):
+        """
+        Externally provided parameters.
+
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
         return relationship.one_to_many(cls, 'input', dict_key='name')
 
     @declared_attr
     def updates(cls):
+        """
+        Service updates.
+
+        :type: [:class:`ServiceUpdate`]
+        """
         return relationship.one_to_many(cls, 'service_update')
 
     @declared_attr
     def modifications(cls):
+        """
+        Service modifications.
+
+        :type: [:class:`ServiceModification`]
+        """
         return relationship.one_to_many(cls, 'service_modification')
 
     @declared_attr
     def executions(cls):
+        """
+        Executions.
+
+        :type: [:class:`Execution`]
+        """
         return relationship.one_to_many(cls, 'execution')
 
     @declared_attr
     def nodes(cls):
+        """
+        Nodes.
+
+        :type: {:obj:`basestring`, :class:`Node`}
+        """
         return relationship.one_to_many(cls, 'node', dict_key='name')
 
     @declared_attr
     def groups(cls):
+        """
+        Groups.
+
+        :type: {:obj:`basestring`, :class:`Group`}
+        """
         return relationship.one_to_many(cls, 'group', dict_key='name')
 
     @declared_attr
     def policies(cls):
+        """
+        Policies.
+
+        :type: {:obj:`basestring`, :class:`Policy`}
+        """
         return relationship.one_to_many(cls, 'policy', dict_key='name')
 
     @declared_attr
     def workflows(cls):
+        """
+        Workflows.
+
+        :type: {:obj:`basestring`, :class:`Operation`}
+        """
         return relationship.one_to_many(cls, 'operation', dict_key='name')
 
     # endregion
@@ -166,6 +168,11 @@ class ServiceBase(InstanceModelMixin):
 
     @declared_attr
     def service_template(cls):
+        """
+        Source service template (can be ``None``).
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     # endregion
@@ -174,18 +181,56 @@ class ServiceBase(InstanceModelMixin):
 
     @declared_attr
     def meta_data(cls):
+        """
+        Associated metadata.
+
+        :type: {:obj:`basestring`, :class:`Metadata`}
+        """
         # Warning! We cannot use the attr name "metadata" because it's used by SQLAlchemy!
         return relationship.many_to_many(cls, 'metadata', dict_key='name')
 
     @declared_attr
     def plugins(cls):
+        """
+        Associated plugins.
+
+        :type: {:obj:`basestring`, :class:`Plugin`}
+        """
         return relationship.many_to_many(cls, 'plugin', dict_key='name')
 
     # endregion
 
-    description = Column(Text)
-    created_at = Column(DateTime, nullable=False, index=True)
-    updated_at = Column(DateTime)
+    # region foreign keys
+
+    @declared_attr
+    def substitution_fk(cls):
+        """Service one-to-one to Substitution"""
+        return relationship.foreign_key('substitution', nullable=True)
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For Service many-to-one to ServiceTemplate"""
+        return relationship.foreign_key('service_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    created_at = Column(DateTime, nullable=False, index=True, doc="""
+    Creation timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    updated_at = Column(DateTime, doc="""
+    Update timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
 
     def satisfy_requirements(self):
         satisfied = True
@@ -311,56 +356,20 @@ class ServiceBase(InstanceModelMixin):
 
 class NodeBase(InstanceModelMixin):
     """
-    Usually an instance of a :class:`NodeTemplate`.
+    Typed vertex in the service topology.
 
-    Nodes may have zero or more :class:`Relationship` instances to other nodes.
-
-    :ivar name: Name (unique for this service)
-    :vartype name: basestring
-    :ivar node_template: Template from which this node was instantiated (optional)
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar type: Node type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interfaces: Bundles of operations
-    :vartype interfaces: {basestring: :class:`Interface`}
-    :ivar artifacts: Associated files
-    :vartype artifacts: {basestring: :class:`Artifact`}
-    :ivar capabilities: Exposed capabilities
-    :vartype capabilities: {basestring: :class:`Capability`}
-    :ivar outbound_relationships: Relationships to other nodes
-    :vartype outbound_relationships: [:class:`Relationship`]
-    :ivar inbound_relationships: Relationships from other nodes
-    :vartype inbound_relationships: [:class:`Relationship`]
-    :ivar host: Host node (can be self)
-    :vartype host: :class:`Node`
-    :ivar state: The state of the node, according to to the TOSCA-defined node states
-    :vartype state: string
-    :ivar version: Used by `aria.storage.instrumentation`
-    :vartype version: int
-    :ivar service: Containing service
-    :vartype service: :class:`Service`
-    :ivar groups: We are a member of these groups
-    :vartype groups: [:class:`Group`]
-    :ivar policies: Policies enacted on this node
-    :vartype policies: [:class:`Policy`]
-    :ivar substitution_mapping: Our contribution to service substitution
-    :vartype substitution_mapping: :class:`SubstitutionMapping`
-    :ivar tasks: Tasks for this node
-    :vartype tasks: [:class:`Task`]
-    :ivar hosted_tasks: Tasks on this node
-    :vartype hosted_tasks: [:class:`Task`]
+    Nodes may have zero or more :class:`Relationship` instances to other nodes, together forming
+    a many-to-many node graph.
+
+    Usually an instance of a :class:`NodeTemplate`.
     """
 
     __tablename__ = 'node'
 
-    __private_fields__ = ['type_fk',
+    __private_fields__ = ('type_fk',
                           'host_fk',
                           'service_fk',
-                          'node_template_fk']
+                          'node_template_fk')
 
     INITIAL = 'initial'
     CREATING = 'creating'
@@ -371,78 +380,33 @@ class NodeBase(InstanceModelMixin):
     STARTED = 'started'
     STOPPING = 'stopping'
     DELETING = 'deleting'
-    # 'deleted' isn't actually part of the tosca spec, since according the description of the
-    # 'deleting' state: "Node is transitioning from its current state to one where it is deleted and
-    #  its state is no longer tracked by the instance model."
-    # However, we prefer to be able to retrieve information about deleted nodes, so we chose to add
-    # this 'deleted' state to enable us to do so.
     DELETED = 'deleted'
     ERROR = 'error'
 
-    STATES = [INITIAL, CREATING, CREATED, CONFIGURING, CONFIGURED, STARTING, STARTED, STOPPING,
-              DELETING, DELETED, ERROR]
+    # 'deleted' isn't actually part of the TOSCA spec, since according the description of the
+    # 'deleting' state: "Node is transitioning from its current state to one where it is deleted and
+    # its state is no longer tracked by the instance model." However, we prefer to be able to
+    # retrieve information about deleted nodes, so we chose to add this 'deleted' state to enable us
+    # to do so.
+
+    STATES = (INITIAL, CREATING, CREATED, CONFIGURING, CONFIGURED, STARTING, STARTED, STOPPING,
+              DELETING, DELETED, ERROR)
 
-    _op_to_state = {'create': {'transitional': CREATING, 'finished': CREATED},
+    _OP_TO_STATE = {'create': {'transitional': CREATING, 'finished': CREATED},
                     'configure': {'transitional': CONFIGURING, 'finished': CONFIGURED},
                     'start': {'transitional': STARTING, 'finished': STARTED},
                     'stop': {'transitional': STOPPING, 'finished': CONFIGURED},
                     'delete': {'transitional': DELETING, 'finished': DELETED}}
 
-    @classmethod
-    def determine_state(cls, op_name, is_transitional):
-        """ :returns the state the node should be in as a result of running the
-            operation on this node.
-
-            e.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
-            the resulting state should either 'creating' (if the task just started) or 'created'
-            (if the task ended).
-
-            If the operation is not a standard tosca lifecycle operation, then we return None"""
-
-        state_type = 'transitional' if is_transitional else 'finished'
-        try:
-            return cls._op_to_state[op_name][state_type]
-        except KeyError:
-            return None
-
-    def is_available(self):
-        return self.state not in (self.INITIAL, self.DELETED, self.ERROR)
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Node many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def host_fk(cls):
-        """For Node one-to-one to Node"""
-        return relationship.foreign_key('node', nullable=True)
-
-    @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Node"""
-        return relationship.foreign_key('service')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For Node many-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template')
-
-    # endregion
-
     # region association proxies
 
     @declared_attr
     def service_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', 'name')
+        return relationship.association_proxy('service', 'name', type=':obj:`basestring`')
 
     @declared_attr
     def node_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('node_template', 'name')
+        return relationship.association_proxy('node_template', 'name', type=':obj:`basestring`')
 
     # endregion
 
@@ -450,6 +414,14 @@ class NodeBase(InstanceModelMixin):
 
     @declared_attr
     def host(cls): # pylint: disable=method-hidden
+        """
+        Node in which we are hosted (can be ``None``).
+
+        Normally the host node is found by following the relationship graph (relationships with
+        ``host`` roles) to final nodes (with ``host`` roles).
+
+        :type: :class:`Node`
+        """
         return relationship.one_to_one_self(cls, 'host_fk')
 
     # endregion
@@ -458,30 +430,65 @@ class NodeBase(InstanceModelMixin):
 
     @declared_attr
     def tasks(cls):
+        """
+        Associated tasks.
+
+        :type: [:class:`Task`]
+        """
         return relationship.one_to_many(cls, 'task')
 
     @declared_attr
     def interfaces(cls):
+        """
+        Associated interfaces.
+
+        :type: {:obj:`basestring`: :class:`Interface`}
+        """
         return relationship.one_to_many(cls, 'interface', dict_key='name')
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     @declared_attr
     def attributes(cls):
+        """
+        Associated mutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Attribute`}
+        """
         return relationship.one_to_many(cls, 'attribute', dict_key='name')
 
     @declared_attr
     def artifacts(cls):
+        """
+        Associated artifacts.
+
+        :type: {:obj:`basestring`: :class:`Artifact`}
+        """
         return relationship.one_to_many(cls, 'artifact', dict_key='name')
 
     @declared_attr
     def capabilities(cls):
+        """
+        Associated exposed capabilities.
+
+        :type: {:obj:`basestring`: :class:`Capability`}
+        """
         return relationship.one_to_many(cls, 'capability', dict_key='name')
 
     @declared_attr
     def outbound_relationships(cls):
+        """
+        Relationships to other nodes.
+
+        :type: [:class:`Relationship`]
+        """
         return relationship.one_to_many(
             cls, 'relationship', other_fk='source_node_fk', back_populates='source_node',
             rel_kwargs=dict(
@@ -492,6 +499,11 @@ class NodeBase(InstanceModelMixin):
 
     @declared_attr
     def inbound_relationships(cls):
+        """
+        Relationships from other nodes.
+
+        :type: [:class:`Relationship`]
+        """
         return relationship.one_to_many(
             cls, 'relationship', other_fk='target_node_fk', back_populates='target_node',
             rel_kwargs=dict(
@@ -506,24 +518,97 @@ class NodeBase(InstanceModelMixin):
 
     @declared_attr
     def service(cls):
+        """
+        Containing service.
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service')
 
     @declared_attr
     def node_template(cls):
+        """
+        Source node template (can be ``None``).
+
+        :type: :class:`NodeTemplate`
+        """
         return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
     def type(cls):
+        """
+        Node type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    description = Column(Text)
-    state = Column(Enum(*STATES, name='node_state'), nullable=False, default=INITIAL)
-    version = Column(Integer, default=1)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Node many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def host_fk(cls):
+        """For Node one-to-one to Node"""
+        return relationship.foreign_key('node', nullable=True)
+
+    @declared_attr
+    def service_fk(cls):
+        """For Service one-to-many to Node"""
+        return relationship.foreign_key('service')
+
+    @declared_attr
+    def node_template_fk(cls):
+        """For Node many-to-one to NodeTemplate"""
+        return relationship.foreign_key('node_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    state = Column(Enum(*STATES, name='node_state'), nullable=False, default=INITIAL, doc="""
+    TOSCA state.
+
+    :type: :obj:`basestring`
+    """)
+
+    version = Column(Integer, default=1, doc="""
+    Used by :mod:`aria.storage.instrumentation`.
+
+    :type: :obj:`int`
+    """)
 
     __mapper_args__ = {'version_id_col': version} # Enable SQLAlchemy automatic version counting
 
+    @classmethod
+    def determine_state(cls, op_name, is_transitional):
+        """ :returns the state the node should be in as a result of running the
+            operation on this node.
+
+            e.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
+            the resulting state should either 'creating' (if the task just started) or 'created'
+            (if the task ended).
+
+            If the operation is not a standard tosca lifecycle operation, then we return None"""
+
+        state_type = 'transitional' if is_transitional else 'finished'
+        try:
+            return cls._OP_TO_STATE[op_name][state_type]
+        except KeyError:
+            return None
+
+    def is_available(self):
+        return self.state not in (self.INITIAL, self.DELETED, self.ERROR)
+
     @property
     def host_address(self):
         if self.host and self.host.attributes:
@@ -698,50 +783,16 @@ class NodeBase(InstanceModelMixin):
 
 class GroupBase(InstanceModelMixin):
     """
-    Usually an instance of a :class:`GroupTemplate`.
+    Typed logical container for zero or more :class:`Node` instances.
 
-    :ivar name: Name (unique for this service)
-    :vartype name: basestring
-    :ivar group_template: Template from which this group was instantiated (optional)
-    :vartype group_template: :class:`GroupTemplate`
-    :ivar type: Group type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar nodes: Members of this group
-    :vartype nodes: [:class:`Node`]
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interfaces: Bundles of operations
-    :vartype interfaces: {basestring: :class:`Interface`}
-    :ivar service: Containing service
-    :vartype service: :class:`Service`
-    :ivar policies: Policies enacted on this group
-    :vartype policies: [:class:`Policy`]
+    Usually an instance of a :class:`GroupTemplate`.
     """
 
     __tablename__ = 'group'
 
-    __private_fields__ = ['type_fk', 'service_fk', 'group_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Group many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Group"""
-        return relationship.foreign_key('service')
-
-    @declared_attr
-    def group_template_fk(cls):
-        """For Group many-to-one to GroupTemplate"""
-        return relationship.foreign_key('group_template', nullable=True)
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'service_fk',
+                          'group_template_fk')
 
     # region association proxies
 
@@ -755,10 +806,20 @@ class GroupBase(InstanceModelMixin):
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     @declared_attr
     def interfaces(cls):
+        """
+        Associated interfaces.
+
+        :type: {:obj:`basestring`: :class:`Interface`}
+        """
         return relationship.one_to_many(cls, 'interface', dict_key='name')
 
     # endregion
@@ -767,14 +828,29 @@ class GroupBase(InstanceModelMixin):
 
     @declared_attr
     def service(cls):
+        """
+        Containing service.
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service')
 
     @declared_attr
     def group_template(cls):
+        """
+        Source group template (can be ``None``).
+
+        :type: :class:`GroupTemplate`
+        """
         return relationship.many_to_one(cls, 'group_template')
 
     @declared_attr
     def type(cls):
+        """
+        Group type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -783,11 +859,39 @@ class GroupBase(InstanceModelMixin):
 
     @declared_attr
     def nodes(cls):
+        """
+        Member nodes.
+
+        :type: [:class:`Node`]
+        """
         return relationship.many_to_many(cls, 'node')
 
     # endregion
 
-    description = Column(Text)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Group many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_fk(cls):
+        """For Service one-to-many to Group"""
+        return relationship.foreign_key('service')
+
+    @declared_attr
+    def group_template_fk(cls):
+        """For Group many-to-one to GroupTemplate"""
+        return relationship.foreign_key('group_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     def configure_operations(self):
         for interface in self.interfaces.itervalues():
@@ -824,48 +928,17 @@ class GroupBase(InstanceModelMixin):
 
 class PolicyBase(InstanceModelMixin):
     """
-    Usually an instance of a :class:`PolicyTemplate`.
+    Typed set of orchestration hints applied to zero or more :class:`Node` or :class:`Group`
+    instances.
 
-    :ivar name: Name (unique for this service)
-    :vartype name: basestring
-    :ivar policy_template: Template from which this policy was instantiated (optional)
-    :vartype policy_template: :class:`PolicyTemplate`
-    :ivar type: Policy type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar nodes: Policy will be enacted on all these nodes
-    :vartype nodes: [:class:`Node`]
-    :ivar groups: Policy will be enacted on all nodes in these groups
-    :vartype groups: [:class:`Group`]
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar service: Containing service
-    :vartype service: :class:`Service`
+    Usually an instance of a :class:`PolicyTemplate`.
     """
 
     __tablename__ = 'policy'
 
-    __private_fields__ = ['type_fk', 'service_fk', 'policy_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Policy many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Policy"""
-        return relationship.foreign_key('service')
-
-    @declared_attr
-    def policy_template_fk(cls):
-        """For Policy many-to-one to PolicyTemplate"""
-        return relationship.foreign_key('policy_template', nullable=True)
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'service_fk',
+                          'policy_template_fk')
 
     # region association proxies
 
@@ -879,6 +952,11 @@ class PolicyBase(InstanceModelMixin):
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -887,14 +965,29 @@ class PolicyBase(InstanceModelMixin):
 
     @declared_attr
     def service(cls):
+        """
+        Containing service.
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service')
 
     @declared_attr
     def policy_template(cls):
+        """
+        Source policy template (can be ``None``).
+
+        :type: :class:`PolicyTemplate`
+        """
         return relationship.many_to_one(cls, 'policy_template')
 
     @declared_attr
     def type(cls):
+        """
+        Group type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -903,15 +996,48 @@ class PolicyBase(InstanceModelMixin):
 
     @declared_attr
     def nodes(cls):
+        """
+        Policy is enacted on these nodes.
+
+        :type: {:obj:`basestring`: :class:`Node`}
+        """
         return relationship.many_to_many(cls, 'node')
 
     @declared_attr
     def groups(cls):
+        """
+        Policy is enacted on nodes in these groups.
+
+        :type: {:obj:`basestring`: :class:`Group`}
+        """
         return relationship.many_to_many(cls, 'group')
 
     # endregion
 
-    description = Column(Text)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Policy many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_fk(cls):
+        """For Service one-to-many to Policy"""
+        return relationship.foreign_key('service')
+
+    @declared_attr
+    def policy_template_fk(cls):
+        """For Policy many-to-one to PolicyTemplate"""
+        return relationship.foreign_key('policy_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     @property
     def as_raw(self):
@@ -946,40 +1072,17 @@ class PolicyBase(InstanceModelMixin):
 
 class SubstitutionBase(InstanceModelMixin):
     """
-    Used to substitute a single node for the entire deployment.
+    Exposes the entire service as a single node.
 
     Usually an instance of a :class:`SubstitutionTemplate`.
-
-    :ivar substitution_template: Template from which this substitution was instantiated (optional)
-    :vartype substitution_template: :class:`SubstitutionTemplate`
-    :ivar node_type: Exposed node type
-    :vartype node_type: :class:`Type`
-    :ivar mappings: Requirement and capability mappings
-    :vartype mappings: {basestring: :class:`SubstitutionTemplate`}
-    :ivar service: Containing service
-    :vartype service: :class:`Service`
     """
 
     __tablename__ = 'substitution'
 
-    __private_fields__ = ['node_type_fk',
-                          'substitution_template_fk']
+    __private_fields__ = ('node_type_fk',
+                          'substitution_template_fk')
 
-    # region foreign_keys
-
-    @declared_attr
-    def node_type_fk(cls):
-        """For Substitution many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def substitution_template_fk(cls):
-        """For Substitution many-to-one to SubstitutionTemplate"""
-        return relationship.foreign_key('substitution_template', nullable=True)
-
-    # endregion
-
-    # region association proxies
+    # region association proxies
 
     # endregion
 
@@ -991,6 +1094,11 @@ class SubstitutionBase(InstanceModelMixin):
 
     @declared_attr
     def mappings(cls):
+        """
+        Map requirement and capabilities to exposed node.
+
+        :type: {:obj:`basestring`: :class:`SubstitutionMapping`}
+        """
         return relationship.one_to_many(cls, 'substitution_mapping', dict_key='name')
 
     # endregion
@@ -999,18 +1107,47 @@ class SubstitutionBase(InstanceModelMixin):
 
     @declared_attr
     def service(cls):
+        """
+        Containing service.
+
+        :type: :class:`Service`
+        """
         return relationship.one_to_one(cls, 'service', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def substitution_template(cls):
+        """
+        Source substitution template (can be ``None``).
+
+        :type: :class:`SubstitutionTemplate`
+        """
         return relationship.many_to_one(cls, 'substitution_template')
 
     @declared_attr
     def node_type(cls):
+        """
+        Exposed node type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
+    # region foreign_keys
+
+    @declared_attr
+    def node_type_fk(cls):
+        """For Substitution many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def substitution_template_fk(cls):
+        """For Substitution many-to-one to SubstitutionTemplate"""
+        return relationship.foreign_key('substitution_template', nullable=True)
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1033,85 +1170,98 @@ class SubstitutionBase(InstanceModelMixin):
 
 class SubstitutionMappingBase(InstanceModelMixin):
     """
-    Used by :class:`Substitution` to map a capability or a requirement to a node.
+    Used by :class:`Substitution` to map a capability or a requirement to the exposed node.
 
-    Only one of `capability_template` and `requirement_template` can be set.
+    The :attr:`name` field should match the capability or requirement template name on the exposed
+    node's type.
 
-    Usually an instance of a :class:`SubstitutionTemplate`.
+    Only one of :attr:`capability` and :attr:`requirement_template` can be set. If the latter is
+    set, then :attr:`node` must also be set.
 
-    :ivar name: Exposed capability or requirement name
-    :vartype name: basestring
-    :ivar node: Node
-    :vartype node: :class:`Node`
-    :ivar capability: Capability in the node
-    :vartype capability: :class:`Capability`
-    :ivar requirement_template: Requirement template in the node template
-    :vartype requirement_template: :class:`RequirementTemplate`
-    :ivar substitution: Containing substitution
-    :vartype substitution: :class:`Substitution`
+    Usually an instance of a :class:`SubstitutionMappingTemplate`.
     """
 
     __tablename__ = 'substitution_mapping'
 
-    __private_fields__ = ['substitution_fk',
-                          'node_fk',
+    __private_fields__ = ('substitution_fk',
                           'capability_fk',
-                          'requirement_template_fk']
+                          'requirement_template_fk',
+                          'node_fk')
 
-    # region foreign keys
+    # region association proxies
 
-    @declared_attr
-    def substitution_fk(cls):
-        """For Substitution one-to-many to SubstitutionMapping"""
-        return relationship.foreign_key('substitution')
+    # endregion
+
+    # region one_to_one relationships
 
     @declared_attr
-    def node_fk(cls):
-        """For Substitution one-to-one to NodeTemplate"""
-        return relationship.foreign_key('node')
+    def capability(cls):
+        """
+        Capability to expose (can be ``None``).
+
+        :type: :class:`Capability`
+        """
+        return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
-    def capability_fk(cls):
-        """For Substitution one-to-one to Capability"""
-        return relationship.foreign_key('capability', nullable=True)
+    def requirement_template(cls):
+        """
+        Requirement template to expose (can be ``None``).
+
+        :type: :class:`RequirementTemplate`
+        """
+        return relationship.one_to_one(cls, 'requirement_template',
+                                       back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
-    def requirement_template_fk(cls):
-        """For Substitution one-to-one to RequirementTemplate"""
-        return relationship.foreign_key('requirement_template', nullable=True)
+    def node(cls):
+        """
+        Node for which to expose :attr:`requirement_template` (can be ``None``).
+
+        :type: :class:`Node`
+        """
+        return relationship.one_to_one(cls, 'node', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    # region association proxies
+    # region one_to_many relationships
 
     # endregion
 
-    # region one_to_one relationships
+    # region many_to_one relationships
 
     @declared_attr
     def substitution(cls):
+        """
+        Containing substitution.
+
+        :type: :class:`Substitution`
+        """
         return relationship.many_to_one(cls, 'substitution', back_populates='mappings')
 
-    @declared_attr
-    def node(cls):
-        return relationship.one_to_one(cls, 'node', back_populates=relationship.NO_BACK_POP)
+    # endregion
 
-    @declared_attr
-    def capability(cls):
-        return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
+    # region foreign keys
 
     @declared_attr
-    def requirement_template(cls):
-        return relationship.one_to_one(
-            cls, 'requirement_template', back_populates=relationship.NO_BACK_POP)
-
-    # endregion
+    def substitution_fk(cls):
+        """For Substitution one-to-many to SubstitutionMapping"""
+        return relationship.foreign_key('substitution')
 
-    # region one_to_many relationships
+    @declared_attr
+    def capability_fk(cls):
+        """For Substitution one-to-one to Capability"""
+        return relationship.foreign_key('capability', nullable=True)
 
-    # endregion
+    @declared_attr
+    def node_fk(cls):
+        """For Substitution one-to-one to Node"""
+        return relationship.foreign_key('node', nullable=True)
 
-    # region many_to_one relationships
+    @declared_attr
+    def requirement_template_fk(cls):
+        """For Substitution one-to-one to RequirementTemplate"""
+        return relationship.foreign_key('requirement_template', nullable=True)
 
     # endregion
 
@@ -1134,102 +1284,46 @@ class SubstitutionMappingBase(InstanceModelMixin):
 
     def dump(self):
         context = ConsumptionContext.get_thread_local()
-        console.puts('{0} -> {1}.{2}'.format(
-            context.style.node(self.name),
-            context.style.node(self.node.name),
-            context.style.node(self.capability.name
-                               if self.capability
-                               else self.requirement_template.name)))
+        if self.capability is not None:
+            console.puts('{0} -> {1}.{2}'.format(
+                context.style.node(self.name),
+                context.style.node(self.capability.node.name),
+                context.style.node(self.capability.name)))
+        else:
+            console.puts('{0} -> {1}.{2}'.format(
+                context.style.node(self.name),
+                context.style.node(self.node.name),
+                context.style.node(self.requirement_template.name)))
 
 
 class RelationshipBase(InstanceModelMixin):
     """
-    Connects :class:`Node` to a capability in another node.
-
-    Might be an instance of a :class:`RelationshipTemplate`.
-
-    :ivar name: Name (usually the name of the requirement at the source node template)
-    :vartype name: basestring
-    :ivar relationship_template: Template from which this relationship was instantiated (optional)
-    :vartype relationship_template: :class:`RelationshipTemplate`
-    :ivar requirement_template: Template from which this relationship was instantiated (optional)
-    :vartype requirement_template: :class:`RequirementTemplate`
-    :ivar type: Relationship type
-    :vartype type: :class:`Type`
-    :ivar target_capability: Capability at the target node (optional)
-    :vartype target_capability: :class:`Capability`
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interfaces: Bundles of operations
-    :vartype interfaces: {basestring: :class:`Interfaces`}
-    :ivar source_position: The position of the relationship in the outbound relationships.
-    :vartype source_position: int
-    :ivar target_position: The position of the relationship in the inbound relationships.
-    :vartype target_position: int
-    :ivar source_node: Source node
-    :vartype source_node: :class:`Node`
-    :ivar target_node: Target node
-    :vartype target_node: :class:`Node`
-    :ivar tasks: Tasks for this relationship
-    :vartype tasks: [:class:`Task`]
+    Optionally-typed edge in the service topology, connecting a :class:`Node` to a
+    :class:`Capability` of another node.
+
+    Might be an instance of :class:`RelationshipTemplate` and/or :class:`RequirementTemplate`.
     """
 
     __tablename__ = 'relationship'
 
-    __private_fields__ = ['type_fk',
+    __private_fields__ = ('type_fk',
                           'source_node_fk',
                           'target_node_fk',
                           'target_capability_fk',
                           'requirement_template_fk',
                           'relationship_template_fk',
                           'target_position',
-                          'source_position']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Relationship many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def source_node_fk(cls):
-        """For Node one-to-many to Relationship"""
-        return relationship.foreign_key('node')
-
-    @declared_attr
-    def target_node_fk(cls):
-        """For Node one-to-many to Relationship"""
-        return relationship.foreign_key('node')
-
-    @declared_attr
-    def target_capability_fk(cls):
-        """For Relationship one-to-one to Capability"""
-        return relationship.foreign_key('capability', nullable=True)
-
-    @declared_attr
-    def requirement_template_fk(cls):
-        """For Relationship many-to-one to RequirementTemplate"""
-        return relationship.foreign_key('requirement_template', nullable=True)
-
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For Relationship many-to-one to RelationshipTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
-
-    # endregion
+                          'source_position')
 
     # region association proxies
 
     @declared_attr
     def source_node_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('source_node', 'name')
+        return relationship.association_proxy('source_node', 'name')
 
     @declared_attr
     def target_node_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('target_node', 'name')
+        return relationship.association_proxy('target_node', 'name')
 
     # endregion
 
@@ -1237,6 +1331,11 @@ class RelationshipBase(InstanceModelMixin):
 
     @declared_attr
     def target_capability(cls):
+        """
+        Target capability.
+
+        :type: :class:`Capability`
+        """
         return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -1245,14 +1344,29 @@ class RelationshipBase(InstanceModelMixin):
 
     @declared_attr
     def tasks(cls):
+        """
+        Associated tasks.
+
+        :type: [:class:`Task`]
+        """
         return relationship.one_to_many(cls, 'task')
 
     @declared_attr
     def interfaces(cls):
+        """
+        Associated interfaces.
+
+        :type: {:obj:`basestring`: :class:`Interface`}
+        """
         return relationship.one_to_many(cls, 'interface', dict_key='name')
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -1261,30 +1375,98 @@ class RelationshipBase(InstanceModelMixin):
 
     @declared_attr
     def source_node(cls):
+        """
+        Source node.
+
+        :type: :class:`Node`
+        """
         return relationship.many_to_one(
             cls, 'node', fk='source_node_fk', back_populates='outbound_relationships')
 
     @declared_attr
     def target_node(cls):
+        """
+        Target node.
+
+        :type: :class:`Node`
+        """
         return relationship.many_to_one(
             cls, 'node', fk='target_node_fk', back_populates='inbound_relationships')
 
     @declared_attr
     def relationship_template(cls):
+        """
+        Source relationship template (can be ``None``).
+
+        :type: :class:`RelationshipTemplate`
+        """
         return relationship.many_to_one(cls, 'relationship_template')
 
     @declared_attr
     def requirement_template(cls):
+        """
+        Source requirement template (can be ``None``).
+
+        :type: :class:`RequirementTemplate`
+        """
         return relationship.many_to_one(cls, 'requirement_template')
 
     @declared_attr
     def type(cls):
+        """
+        Relationship type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    source_position = Column(Integer)
-    target_position = Column(Integer)
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Relationship many-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def source_node_fk(cls):
+        """For Node one-to-many to Relationship"""
+        return relationship.foreign_key('node')
+
+    @declared_attr
+    def target_node_fk(cls):
+        """For Node one-to-many to Relationship"""
+        return relationship.foreign_key('node')
+
+    @declared_attr
+    def target_capability_fk(cls):
+        """For Relationship one-to-one to Capability"""
+        return relationship.foreign_key('capability', nullable=True)
+
+    @declared_attr
+    def requirement_template_fk(cls):
+        """For Relationship many-to-one to RequirementTemplate"""
+        return relationship.foreign_key('requirement_template', nullable=True)
+
+    @declared_attr
+    def relationship_template_fk(cls):
+        """For Relationship many-to-one to RelationshipTemplate"""
+        return relationship.foreign_key('relationship_template', nullable=True)
+
+    # endregion
+
+    source_position = Column(Integer, doc="""
+    Position at source.
+
+    :type: :obj:`int`
+    """)
+
+    target_position = Column(Integer, doc="""
+    Position at target.
+
+    :type: :obj:`int`
+    """)
 
     def configure_operations(self):
         for interface in self.interfaces.itervalues():
@@ -1332,56 +1514,17 @@ class RelationshipBase(InstanceModelMixin):
 
 class CapabilityBase(InstanceModelMixin):
     """
-    A capability of a :class:`Node`.
+    Typed attachment serving two purposes: to provide extra properties and attributes to a
+    :class:`Node`, and to expose targets for :class:`Relationship` instances from other nodes.
 
     Usually an instance of a :class:`CapabilityTemplate`.
-
-    :ivar name: Name (unique for the node)
-    :vartype name: basestring
-    :ivar capability_template: Template from which this capability was instantiated (optional)
-    :vartype capability_template: :class:`capabilityTemplate`
-    :ivar type: Capability type
-    :vartype type: :class:`Type`
-    :ivar min_occurrences: Minimum number of requirement matches required
-    :vartype min_occurrences: int
-    :ivar max_occurrences: Maximum number of requirement matches allowed
-    :vartype min_occurrences: int
-    :ivar occurrences: Actual number of requirement matches
-    :vartype occurrences: int
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar node: Containing node
-    :vartype node: :class:`Node`
-    :ivar relationship: Available when we are the target of a relationship
-    :vartype relationship: :class:`Relationship`
-    :ivar substitution_mapping: Our contribution to service substitution
-    :vartype substitution_mapping: :class:`SubstitutionMapping`
     """
 
     __tablename__ = 'capability'
 
-    __private_fields__ = ['capability_fk',
+    __private_fields__ = ('capability_fk',
                           'node_fk',
-                          'capability_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Capability many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_fk(cls):
-        """For Node one-to-many to Capability"""
-        return relationship.foreign_key('node')
-
-    @declared_attr
-    def capability_template_fk(cls):
-        """For Capability many-to-one to CapabilityTemplate"""
-        return relationship.foreign_key('capability_template', nullable=True)
-
-    # endregion
+                          'capability_template_fk')
 
     # region association proxies
 
@@ -1395,6 +1538,11 @@ class CapabilityBase(InstanceModelMixin):
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -1403,21 +1551,69 @@ class CapabilityBase(InstanceModelMixin):
 
     @declared_attr
     def node(cls):
+        """
+        Containing node.
+
+        :type: :class:`Node`
+        """
         return relationship.many_to_one(cls, 'node')
 
     @declared_attr
     def capability_template(cls):
+        """
+        Source capability template (can be ``None``).
+
+        :type: :class:`CapabilityTemplate`
+        """
         return relationship.many_to_one(cls, 'capability_template')
 
     @declared_attr
     def type(cls):
+        """
+        Capability type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    min_occurrences = Column(Integer, default=None)
-    max_occurrences = Column(Integer, default=None)
-    occurrences = Column(Integer, default=0)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Capability many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_fk(cls):
+        """For Node one-to-many to Capability"""
+        return relationship.foreign_key('node')
+
+    @declared_attr
+    def capability_template_fk(cls):
+        """For Capability many-to-one to CapabilityTemplate"""
+        return relationship.foreign_key('capability_template', nullable=True)
+
+    # endregion
+
+    min_occurrences = Column(Integer, default=None, doc="""
+    Minimum number of requirement matches required.
+
+    :type: :obj:`int`
+    """)
+
+    max_occurrences = Column(Integer, default=None, doc="""
+    Maximum number of requirement matches allowed.
+
+    :type: :obj:`int`
+    """)
+
+    occurrences = Column(Integer, default=0, doc="""
+    Number of requirement matches.
+
+    :type: :obj:`int`
+    """)
 
     @property
     def has_enough_relationships(self):
@@ -1461,66 +1657,20 @@ class CapabilityBase(InstanceModelMixin):
 
 class InterfaceBase(InstanceModelMixin):
     """
-    A typed set of :class:`Operation`.
-
-    Usually an instance of :class:`InterfaceTemplate`.
-
-    :ivar name: Name (unique for the node, group, or relationship)
-    :vartype name: basestring
-    :ivar interface_template: Template from which this interface was instantiated (optional)
-    :vartype interface_template: :class:`InterfaceTemplate`
-    :ivar type: Interface type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar inputs: Inputs that can be used by all operations in the interface
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar operations: Operations
-    :vartype operations: {basestring: :class:`Operation`}
-    :ivar node: Containing node
-    :vartype node: :class:`Node`
-    :ivar group: Containing group
-    :vartype group: :class:`Group`
-    :ivar relationship: Containing relationship
-    :vartype relationship: :class:`Relationship`
+    Typed bundle of :class:`Operation` instances.
+
+    Can be associated with a :class:`Node`, a :class:`Group`, or a :class:`Relationship`.
+
+    Usually an instance of a :class:`InterfaceTemplate`.
     """
 
     __tablename__ = 'interface'
 
-    __private_fields__ = ['type_fk',
+    __private_fields__ = ('type_fk',
                           'node_fk',
                           'group_fk',
                           'relationship_fk',
-                          'interface_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Interface many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_fk(cls):
-        """For Node one-to-many to Interface"""
-        return relationship.foreign_key('node', nullable=True)
-
-    @declared_attr
-    def group_fk(cls):
-        """For Group one-to-many to Interface"""
-        return relationship.foreign_key('group', nullable=True)
-
-    @declared_attr
-    def relationship_fk(cls):
-        """For Relationship one-to-many to Interface"""
-        return relationship.foreign_key('relationship', nullable=True)
-
-    @declared_attr
-    def interface_template_fk(cls):
-        """For Interface many-to-one to InterfaceTemplate"""
-        return relationship.foreign_key('interface_template', nullable=True)
-
-    # endregion
+                          'interface_template_fk')
 
     # region association proxies
 
@@ -1534,10 +1684,20 @@ class InterfaceBase(InstanceModelMixin):
 
     @declared_attr
     def inputs(cls):
+        """
+        Parameters for all operations of the interface.
+
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
         return relationship.one_to_many(cls, 'input', dict_key='name')
 
     @declared_attr
     def operations(cls):
+        """
+        Associated operations.
+
+        :type: {:obj:`basestring`: :class:`Operation`}
+        """
         return relationship.one_to_many(cls, 'operation', dict_key='name')
 
     # endregion
@@ -1546,27 +1706,85 @@ class InterfaceBase(InstanceModelMixin):
 
     @declared_attr
     def node(cls):
-        return relationship.many_to_one(cls, 'node')
+        """
+        Containing node (can be ``None``).
 
-    @declared_attr
-    def relationship(cls):
-        return relationship.many_to_one(cls, 'relationship')
+        :type: :class:`Node`
+        """
+        return relationship.many_to_one(cls, 'node')
 
     @declared_attr
     def group(cls):
+        """
+        Containing group (can be ``None``).
+
+        :type: :class:`Group`
+        """
         return relationship.many_to_one(cls, 'group')
 
     @declared_attr
+    def relationship(cls):
+        """
+        Containing relationship (can be ``None``).
+
+        :type: :class:`Relationship`
+        """
+        return relationship.many_to_one(cls, 'relationship')
+
+    @declared_attr
     def interface_template(cls):
+        """
+        Source interface template (can be ``None``).
+
+        :type: :class:`InterfaceTemplate`
+        """
         return relationship.many_to_one(cls, 'interface_template')
 
     @declared_attr
     def type(cls):
+        """
+        Interface type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    description = Column(Text)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Interface many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_fk(cls):
+        """For Node one-to-many to Interface"""
+        return relationship.foreign_key('node', nullable=True)
+
+    @declared_attr
+    def group_fk(cls):
+        """For Group one-to-many to Interface"""
+        return relationship.foreign_key('group', nullable=True)
+
+    @declared_attr
+    def relationship_fk(cls):
+        """For Relationship one-to-many to Interface"""
+        return relationship.foreign_key('relationship', nullable=True)
+
+    @declared_attr
+    def interface_template_fk(cls):
+        """For Interface many-to-one to InterfaceTemplate"""
+        return relationship.foreign_key('interface_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     def configure_operations(self):
         for operation in self.operations.itervalues():
@@ -1602,76 +1820,29 @@ class InterfaceBase(InstanceModelMixin):
 
 class OperationBase(InstanceModelMixin):
     """
-    An operation in a :class:`Interface`.
+    Entry points to Python functions called as part of a workflow execution.
 
-    Might be an instance of :class:`OperationTemplate`.
+    The operation signature (its :attr:`name` and its :attr:`inputs`'s names and types) is declared
+    by the type of the :class:`Interface`, however each operation can provide its own
+    :attr:`implementation` as well as additional inputs.
 
-    :ivar name: Name (unique for the interface or service)
-    :vartype name: basestring
-    :ivar operation_template: Template from which this operation was instantiated (optional)
-    :vartype operation_template: :class:`OperationTemplate`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar relationship_edge: When true specified that the operation is on the relationship's
-                             target edge instead of its source (only used by relationship
-                             operations)
-    :vartype relationship_edge: bool
-    :ivar implementation: Implementation (interpreted by the plugin)
-    :vartype implementation: basestring
-    :ivar dependencies: Dependency strings (interpreted by the plugin)
-    :vartype dependencies: [basestring]
-    :ivar inputs: Input that can be used by this operation
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar plugin: Associated plugin
-    :vartype plugin: :class:`Plugin`
-    :ivar configurations: Configuration (interpreted by the plugin)
-    :vartype configurations: {basestring, :class:`Configuration`}
-    :ivar function: Name of the operation function
-    :vartype function: basestring
-    :ivar arguments: Arguments to send to the operation function
-    :vartype arguments: {basestring: :class:`Argument`}
-    :ivar executor: Name of executor to run the operation with
-    :vartype executor: basestring
-    :ivar max_attempts: Maximum number of attempts allowed in case of failure
-    :vartype max_attempts: int
-    :ivar retry_interval: Interval between retries (in seconds)
-    :vartype retry_interval: int
-    :ivar interface: Containing interface
-    :vartype interface: :class:`Interface`
-    :ivar service: Containing service
-    :vartype service: :class:`Service`
+    The Python :attr:`function` is usually provided by an associated :class:`Plugin`. Its purpose is
+    to execute the implementation, providing it with both the operation's and interface's inputs.
+    The :attr:`arguments` of the function should be set according to the specific signature of the
+    function.
+
+    Additionally, :attr:`configuration` parameters can be provided as hints to configure the
+    function's behavior. For example, they can be used to configure remote execution credentials.
+
+    Might be an instance of :class:`OperationTemplate`.
     """
 
     __tablename__ = 'operation'
 
-    __private_fields__ = ['service_fk',
+    __private_fields__ = ('service_fk',
                           'interface_fk',
                           'plugin_fk',
-                          'operation_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def service_fk(cls):
-        """For Service one-to-many to Operation"""
-        return relationship.foreign_key('service', nullable=True)
-
-    @declared_attr
-    def interface_fk(cls):
-        """For Interface one-to-many to Operation"""
-        return relationship.foreign_key('interface', nullable=True)
-
-    @declared_attr
-    def plugin_fk(cls):
-        """For Operation one-to-one to Plugin"""
-        return relationship.foreign_key('plugin', nullable=True)
-
-    @declared_attr
-    def operation_template_fk(cls):
-        """For Operation many-to-one to OperationTemplate"""
-        return relationship.foreign_key('operation_template', nullable=True)
-
-    # endregion
+                          'operation_template_fk')
 
     # region association proxies
 
@@ -1681,6 +1852,11 @@ class OperationBase(InstanceModelMixin):
 
     @declared_attr
     def plugin(cls):
+        """
+        Associated plugin.
+
+        :type: :class:`Plugin`
+        """
         return relationship.one_to_one(cls, 'plugin', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -1689,30 +1865,60 @@ class OperationBase(InstanceModelMixin):
 
     @declared_attr
     def inputs(cls):
-        return relationship.one_to_many(cls, 'input', dict_key='name')
+        """
+        Parameters provided to the :attr:`implementation`.
 
-    @declared_attr
-    def configurations(cls):
-        return relationship.one_to_many(cls, 'configuration', dict_key='name')
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
+        return relationship.one_to_many(cls, 'input', dict_key='name')
 
     @declared_attr
     def arguments(cls):
+        """
+        Arguments sent to the Python :attr:`function`.
+
+        :type: {:obj:`basestring`: :class:`Argument`}
+        """
         return relationship.one_to_many(cls, 'argument', dict_key='name')
 
+    @declared_attr
+    def configurations(cls):
+        """
+        Configuration parameters for the Python :attr:`function`.
+
+        :type: {:obj:`basestring`: :class:`Configuration`}
+        """
+        return relationship.one_to_many(cls, 'configuration', dict_key='name')
+
     # endregion
 
     # region many_to_one relationships
 
     @declared_attr
     def service(cls):
+        """
+        Containing service (can be ``None``). For workflow operations.
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service', back_populates='workflows')
 
     @declared_attr
     def interface(cls):
+        """
+        Containing interface (can be ``None``).
+
+        :type: :class:`Interface`
+        """
         return relationship.many_to_one(cls, 'interface')
 
     @declared_attr
     def operation_template(cls):
+        """
+        Source operation template (can be ``None``).
+
+        :type: :class:`OperationTemplate`
+        """
         return relationship.many_to_one(cls, 'operation_template')
 
     # endregion
@@ -1721,14 +1927,78 @@ class OperationBase(InstanceModelMixin):
 
     # endregion
 
-    description = Column(Text)
-    relationship_edge = Column(Boolean)
-    implementation = Column(Text)
-    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-    function = Column(Text)
-    executor = Column(Text)
-    max_attempts = Column(Integer)
-    retry_interval = Column(Integer)
+    # region foreign_keys
+
+    @declared_attr
+    def service_fk(cls):
+        """For Service one-to-many to Operation"""
+        return relationship.foreign_key('service', nullable=True)
+
+    @declared_attr
+    def interface_fk(cls):
+        """For Interface one-to-many to Operation"""
+        return relationship.foreign_key('interface', nullable=True)
+
+    @declared_attr
+    def plugin_fk(cls):
+        """For Operation one-to-one to Plugin"""
+        return relationship.foreign_key('plugin', nullable=True)
+
+    @declared_attr
+    def operation_template_fk(cls):
+        """For Operation many-to-one to OperationTemplate"""
+        return relationship.foreign_key('operation_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    relationship_edge = Column(Boolean, doc="""
+    When ``True`` specifies that the operation is on the relationship's target edge; ``False`` is
+    the source edge (only used by operations on relationships)
+
+    :type: :obj:`bool`
+    """)
+
+    implementation = Column(Text, doc="""
+    Implementation (usually the name of an artifact).
+
+    :type: :obj:`basestring`
+    """)
+
+    dependencies = Column(modeling_types.StrictList(item_cls=basestring), doc="""
+    Dependencies (usually names of artifacts).
+
+    :type: [:obj:`basestring`]
+    """)
+
+    function = Column(Text, doc="""
+    Full path to Python function.
+
+    :type: :obj:`basestring`
+    """)
+
+    executor = Column(Text, doc="""
+    Name of executor.
+
+    :type: :obj:`basestring`
+    """)
+
+    max_attempts = Column(Integer, doc="""
+    Maximum number of attempts allowed in case of task failure.
+
+    :type: :obj:`int`
+    """)
+
+    retry_interval = Column(Integer, doc="""
+    Interval between task retry attemps (in seconds).
+
+    :type: :obj:`float`
+    """)
 
     def configure(self):
         if (self.implementation is None) and (self.function is None):
@@ -1821,56 +2091,16 @@ class OperationBase(InstanceModelMixin):
 
 class ArtifactBase(InstanceModelMixin):
     """
-    A file associated with a :class:`Node`.
+    Typed file, either provided in a CSAR or downloaded from a repository.
 
     Usually an instance of :class:`ArtifactTemplate`.
-
-    :ivar name: Name (unique for the node)
-    :vartype name: basestring
-    :ivar artifact_template: Template from which this artifact was instantiated (optional)
-    :vartype artifact_template: :class:`ArtifactTemplate`
-    :ivar type: Artifact type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: string
-    :ivar source_path: Source path (CSAR or repository)
-    :vartype source_path: basestring
-    :ivar target_path: Path at destination machine
-    :vartype target_path: basestring
-    :ivar repository_url: Repository URL
-    :vartype repository_path: basestring
-    :ivar repository_credential: Credentials for accessing the repository
-    :vartype repository_credential: {basestring: basestring}
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar node: Containing node
-    :vartype node: :class:`Node`
     """
 
     __tablename__ = 'artifact'
 
-    __private_fields__ = ['type_fk',
+    __private_fields__ = ('type_fk',
                           'node_fk',
-                          'artifact_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For Artifact many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_fk(cls):
-        """For Node one-to-many to Artifact"""
-        return relationship.foreign_key('node')
-
-    @declared_attr
-    def artifact_template_fk(cls):
-        """For Artifact many-to-one to ArtifactTemplate"""
-        return relationship.foreign_key('artifact_template', nullable=True)
-
-    # endregion
+                          'artifact_template_fk')
 
     # region association proxies
 
@@ -1884,29 +2114,94 @@ class ArtifactBase(InstanceModelMixin):
 
     @declared_attr
     def properties(cls):
+        """
+        Associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
 
     # region many_to_one relationships
+
     @declared_attr
     def node(cls):
+        """
+        Containing node.
+
+        :type: :class:`Node`
+        """
         return relationship.many_to_one(cls, 'node')
 
     @declared_attr
     def artifact_template(cls):
+        """
+        Source artifact template (can be ``None``).
+
+        :type: :class:`ArtifactTemplate`
+        """
         return relationship.many_to_one(cls, 'artifact_template')
 
     @declared_attr
     def type(cls):
+        """
+        Artifact type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
+
+    # endregion
+
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For Artifact many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_fk(cls):
+        """For Node one-to-many to Artifact"""
+        return relationship.foreign_key('node')
+
+    @declared_attr
+    def artifact_template_fk(cls):
+        """For Artifact many-to-one to ArtifactTemplate"""
+        return relationship.foreign_key('artifact_template', nullable=True)
+
     # endregion
 
-    description = Column(Text)
-    source_path = Column(Text)
-    target_path = Column(Text)
-    repository_url = Column(Text)
-    repository_credential = Column(modeling_types.StrictDict(basestring, basestring))
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    source_path = Column(Text, doc="""
+    Source path (in CSAR or repository).
+
+    :type: :obj:`basestring`
+    """)
+
+    target_path = Column(Text, doc="""
+    Path at which to install at destination.
+
+    :type: :obj:`basestring`
+    """)
+
+    repository_url = Column(Text, doc="""
+    Repository URL.
+
+    :type: :obj:`basestring`
+    """)
+
+    repository_credential = Column(modeling_types.StrictDict(basestring, basestring), doc="""
+    Credentials for accessing the repository.
+
+    :type: {:obj:`basestring`, :obj:`basestring`}
+    """)
 
     @property
     def as_raw(self):


[12/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 344da6d..57fd672 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+ARIA modeling service template module
+"""
+
 # pylint: disable=too-many-lines, no-self-argument, no-member, abstract-method
 
 from __future__ import absolute_import  # so we can import standard 'types'
@@ -28,7 +32,6 @@ from sqlalchemy import (
     PickleType
 )
 from sqlalchemy.ext.declarative import declared_attr
-from sqlalchemy.ext.associationproxy import association_proxy
 
 from ..parser import validation
 from ..parser.consumption import ConsumptionContext
@@ -45,116 +48,46 @@ from . import (
 
 class ServiceTemplateBase(TemplateModelMixin):
     """
-    A service template is a source for creating :class:`Service` instances.
-
-    It is usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can
-    also be created programmatically.
-
-    :ivar name: Name (unique for this ARIA installation)
-    :vartype name: basestring
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar main_file_name: Filename of CSAR or YAML file from which this service template was parsed
-    :vartype main_file_name: basestring
-    :ivar meta_data: Custom annotations
-    :vartype meta_data: {basestring: :class:`Metadata`}
-    :ivar node_templates: Templates for creating nodes
-    :vartype node_templates: {basestring: :class:`NodeTemplate`}
-    :ivar group_templates: Templates for creating groups
-    :vartype group_templates: {basestring: :class:`GroupTemplate`}
-    :ivar policy_templates: Templates for creating policies
-    :vartype policy_templates: {basestring: :class:`PolicyTemplate`}
-    :ivar substitution_template: The entire service can appear as a node
-    :vartype substitution_template: :class:`SubstitutionTemplate`
-    :ivar inputs: Externally provided parameters
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar outputs: These parameters are filled in after service installation
-    :vartype outputs: {basestring: :class:`Output`}
-    :ivar workflow_templates: Custom workflows that can be performed on the service
-    :vartype workflow_templates: {basestring: :class:`OperationTemplate`}
-    :ivar plugin_specifications: Plugins used by the service
-    :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
-    :ivar node_types: Base for the node type hierarchy
-    :vartype node_types: :class:`Type`
-    :ivar group_types: Base for the group type hierarchy
-    :vartype group_types: :class:`Type`
-    :ivar policy_types: Base for the policy type hierarchy
-    :vartype policy_types: :class:`Type`
-    :ivar relationship_types: Base for the relationship type hierarchy
-    :vartype relationship_types: :class:`Type`
-    :ivar capability_types: Base for the capability type hierarchy
-    :vartype capability_types: :class:`Type`
-    :ivar interface_types: Base for the interface type hierarchy
-    :vartype interface_types: :class:`Type`
-    :ivar artifact_types: Base for the artifact type hierarchy
-    :vartype artifact_types: :class:`Type`
-    :ivar created_at: Creation timestamp
-    :vartype created_at: :class:`datetime.datetime`
-    :ivar updated_at: Update timestamp
-    :vartype updated_at: :class:`datetime.datetime`
-    :ivar services: Instantiated services
-    :vartype services: [:class:`Service`]
+    Template for creating :class:`Service` instances.
+
+    Usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can also be
+    created programmatically.
     """
 
     __tablename__ = 'service_template'
 
-    __private_fields__ = ['substitution_template_fk',
+    __private_fields__ = ('substitution_template_fk',
                           'node_type_fk',
                           'group_type_fk',
                           'policy_type_fk',
                           'relationship_type_fk',
                           'capability_type_fk',
                           'interface_type_fk',
-                          'artifact_type_fk']
-
-    description = Column(Text)
-    main_file_name = Column(Text)
-    created_at = Column(DateTime, nullable=False, index=True)
-    updated_at = Column(DateTime)
-
-    # region foreign keys
-
-    @declared_attr
-    def substitution_template_fk(cls):
-        """For ServiceTemplate one-to-one to SubstitutionTemplate"""
-        return relationship.foreign_key('substitution_template', nullable=True)
-
-    @declared_attr
-    def node_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+                          'artifact_type_fk')
 
-    @declared_attr
-    def group_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    description = Column(Text, doc="""
+    Human-readable description.
 
-    @declared_attr
-    def policy_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    :type: :obj:`basestring`
+    """)
 
-    @declared_attr
-    def relationship_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    main_file_name = Column(Text, doc="""
+    Filename of CSAR or YAML file from which this service template was parsed.
+    
+    :type: :obj:`basestring`
+    """)
 
-    @declared_attr
-    def capability_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    created_at = Column(DateTime, nullable=False, index=True, doc="""
+    Creation timestamp.
 
-    @declared_attr
-    def interface_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    :type: :class:`~datetime.datetime`
+    """)
 
-    @declared_attr
-    def artifact_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    updated_at = Column(DateTime, doc="""
+    Update timestamp.
 
-    # endregion
+    :type: :class:`~datetime.datetime`
+    """)
 
     # region association proxies
 
@@ -164,41 +97,81 @@ class ServiceTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def substitution_template(cls):
+        """
+        Exposes an entire service as a single node.
+
+        :type: :class:`SubstitutionTemplate`
+        """
         return relationship.one_to_one(
             cls, 'substitution_template', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def node_types(cls):
+        """
+        Base for the node type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='node_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def group_types(cls):
+        """
+        Base for the group type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='group_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def policy_types(cls):
+        """
+        Base for the policy type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='policy_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def relationship_types(cls):
+        """
+        Base for the relationship type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='relationship_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def capability_types(cls):
+        """
+        Base for the capability type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='capability_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def interface_types(cls):
+        """
+        Base for the interface type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='interface_type_fk', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def artifact_types(cls):
+        """
+        Base for the artifact type hierarchy,
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one(
             cls, 'type', fk='artifact_type_fk', back_populates=relationship.NO_BACK_POP)
 
@@ -208,34 +181,74 @@ class ServiceTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def services(cls):
+        """
+        Instantiated services.
+
+        :type: [:class:`Service`]
+        """
         return relationship.one_to_many(cls, 'service', dict_key='name')
 
     @declared_attr
     def node_templates(cls):
-        return relationship.one_to_many(cls, 'node_template', dict_key='name')
-
-    @declared_attr
-    def outputs(cls):
-        return relationship.one_to_many(cls, 'output', dict_key='name')
+        """
+        Templates for creating nodes.
 
-    @declared_attr
-    def inputs(cls):
-        return relationship.one_to_many(cls, 'input', dict_key='name')
+        :type: {:obj:`basestring`, :class:`NodeTemplate`}
+        """
+        return relationship.one_to_many(cls, 'node_template', dict_key='name')
 
     @declared_attr
     def group_templates(cls):
+        """
+        Templates for creating groups.
+
+        :type: {:obj:`basestring`, :class:`GroupTemplate`}
+        """
         return relationship.one_to_many(cls, 'group_template', dict_key='name')
 
     @declared_attr
     def policy_templates(cls):
+        """
+        Templates for creating policies.
+
+        :type: {:obj:`basestring`, :class:`PolicyTemplate`}
+        """
         return relationship.one_to_many(cls, 'policy_template', dict_key='name')
 
     @declared_attr
     def workflow_templates(cls):
+        """
+        Templates for creating workflows.
+
+        :type: {:obj:`basestring`, :class:`OperationTemplate`}
+        """
         return relationship.one_to_many(cls, 'operation_template', dict_key='name')
 
     @declared_attr
+    def outputs(cls):
+        """
+        Declarations for output parameters are filled in after service installation.
+
+        :type: {:obj:`basestring`: :class:`Output`}
+        """
+        return relationship.one_to_many(cls, 'output', dict_key='name')
+
+    @declared_attr
+    def inputs(cls):
+        """
+        Declarations for externally provided parameters.
+
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
+        return relationship.one_to_many(cls, 'input', dict_key='name')
+
+    @declared_attr
     def plugin_specifications(cls):
+        """
+        Required plugins for instantiated services.
+
+        :type: {:obj:`basestring`: :class:`PluginSpecification`}
+        """
         return relationship.one_to_many(cls, 'plugin_specification', dict_key='name')
 
     # endregion
@@ -248,11 +261,60 @@ class ServiceTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def meta_data(cls):
+        """
+        Associated metadata.
+
+        :type: {:obj:`basestring`: :class:`Metadata`}
+        """
         # Warning! We cannot use the attr name "metadata" because it's used by SQLAlchemy!
         return relationship.many_to_many(cls, 'metadata', dict_key='name')
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def substitution_template_fk(cls):
+        """For ServiceTemplate one-to-one to SubstitutionTemplate"""
+        return relationship.foreign_key('substitution_template', nullable=True)
+
+    @declared_attr
+    def node_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def group_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def policy_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def relationship_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def capability_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def interface_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def artifact_type_fk(cls):
+        """For ServiceTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -397,75 +459,24 @@ class ServiceTemplateBase(TemplateModelMixin):
 
 class NodeTemplateBase(TemplateModelMixin):
     """
-    A template for creating zero or more :class:`Node` instances.
-
-    :ivar name: Name (unique for this service template; will usually be used as a prefix for node
-                names)
-    :vartype name: basestring
-    :ivar type: Node type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar default_instances: Default number nodes that will appear in the service
-    :vartype default_instances: int
-    :ivar min_instances: Minimum number nodes that will appear in the service
-    :vartype min_instances: int
-    :ivar max_instances: Maximum number nodes that will appear in the service
-    :vartype max_instances: int
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interface_templates: Bundles of operations
-    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
-    :ivar artifact_templates: Associated files
-    :vartype artifact_templates: {basestring: :class:`ArtifactTemplate`}
-    :ivar capability_templates: Exposed capabilities
-    :vartype capability_templates: {basestring: :class:`CapabilityTemplate`}
-    :ivar requirement_templates: Potential relationships with other nodes
-    :vartype requirement_templates: [:class:`RequirementTemplate`]
-    :ivar target_node_template_constraints: Constraints for filtering relationship targets
-    :vartype target_node_template_constraints: [:class:`NodeTemplateConstraint`]
-    :ivar service_template: Containing service template
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar group_templates: We are a member of these groups
-    :vartype group_templates: [:class:`GroupTemplate`]
-    :ivar policy_templates: Policy templates enacted on this node
-    :vartype policy_templates: [:class:`PolicyTemplate`]
-    :ivar substitution_template_mapping: Our contribution to service substitution
-    :vartype substitution_template_mapping: :class:`SubstitutionTemplateMapping`
-    :ivar nodes: Instantiated nodes
-    :vartype nodes: [:class:`Node`]
+    Template for creating zero or more :class:`Node` instances, which are typed vertices in the
+    service topology.
     """
 
     __tablename__ = 'node_template'
 
-    __private_fields__ = ['type_fk',
-                          'service_template_fk']
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For NodeTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to NodeTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'service_template_fk')
 
     # region association proxies
 
     @declared_attr
     def service_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service_template', 'name')
+        return relationship.association_proxy('service_template', 'name')
 
     @declared_attr
     def type_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('type', 'name')
+        return relationship.association_proxy('type', 'name')
 
     # endregion
 
@@ -477,30 +488,65 @@ class NodeTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def nodes(cls):
+        """
+        Instantiated nodes.
+
+        :type: [:class:`Node`]
+        """
         return relationship.one_to_many(cls, 'node')
 
     @declared_attr
     def interface_templates(cls):
+        """
+        Associated interface templates.
+
+        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+        """
         return relationship.one_to_many(cls, 'interface_template', dict_key='name')
 
     @declared_attr
     def artifact_templates(cls):
+        """
+        Associated artifacts.
+
+        :type: {:obj:`basestring`: :class:`ArtifactTemplate`}
+        """
         return relationship.one_to_many(cls, 'artifact_template', dict_key='name')
 
     @declared_attr
     def capability_templates(cls):
+        """
+        Associated exposed capability templates.
+
+        :type: {:obj:`basestring`: :class:`CapabilityTemplate`}
+        """
         return relationship.one_to_many(cls, 'capability_template', dict_key='name')
 
     @declared_attr
     def requirement_templates(cls):
+        """
+        Associated potential relationships with other nodes.
+
+        :type: [:class:`RequirementTemplate`]
+        """
         return relationship.one_to_many(cls, 'requirement_template', other_fk='node_template_fk')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     @declared_attr
     def attributes(cls):
+        """
+        Declarations for associated mutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Attribute`}
+        """
         return relationship.one_to_many(cls, 'attribute', dict_key='name')
 
     # endregion
@@ -509,19 +555,67 @@ class NodeTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def type(cls):
+        """
+        Node type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template.
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     # endregion
 
-    description = Column(Text)
-    default_instances = Column(Integer, default=1)
-    min_instances = Column(Integer, default=0)
-    max_instances = Column(Integer, default=None)
-    target_node_template_constraints = Column(PickleType)
+    # region foreign_keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For NodeTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to NodeTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    default_instances = Column(Integer, default=1, doc="""
+    Default number nodes that will appear in the service.
+
+    :type: :obj:`int`
+    """)
+
+    min_instances = Column(Integer, default=0, doc="""
+    Minimum number nodes that will appear in the service.
+
+    :type: :obj:`int`
+    """)
+
+    max_instances = Column(Integer, default=None, doc="""
+    Maximum number nodes that will appear in the service.
+
+    :type: :obj:`int`
+    """)
+
+    target_node_template_constraints = Column(PickleType, doc="""
+    Constraints for filtering relationship targets.
+
+    :type: [:class:`NodeTemplateConstraint`]
+    """)
 
     def is_target_node_template_valid(self, target_node_template):
         if self.target_node_template_constraints:
@@ -612,48 +706,14 @@ class NodeTemplateBase(TemplateModelMixin):
 
 class GroupTemplateBase(TemplateModelMixin):
     """
-    A template for creating a :class:`Group` instance.
-
-    Groups are logical containers for zero or more nodes.
-
-    :ivar name: Name (unique for this service template)
-    :vartype name: basestring
-    :ivar type: Group type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar node_templates: All nodes instantiated by these templates will be members of the group
-    :vartype node_templates: [:class:`NodeTemplate`]
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interface_templates: Bundles of operations
-    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
-    :ivar service_template: Containing service template
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar policy_templates: Policy templates enacted on this group
-    :vartype policy_templates: [:class:`PolicyTemplate`]
-    :ivar groups: Instantiated groups
-    :vartype groups: [:class:`Group`]
+    Template for creating a :class:`Group` instance, which is a typed logical container for zero or
+    more :class:`Node` instances.
     """
 
     __tablename__ = 'group_template'
 
-    __private_fields__ = ['type_fk',
-                          'service_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For GroupTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to GroupTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'service_template_fk')
 
     # region association proxies
 
@@ -667,14 +727,29 @@ class GroupTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def groups(cls):
+        """
+        Instantiated groups.
+
+        :type: [:class:`Group`]
+        """
         return relationship.one_to_many(cls, 'group')
 
     @declared_attr
     def interface_templates(cls):
+        """
+        Associated interface templates.
+
+        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+        """
         return relationship.one_to_many(cls, 'interface_template', dict_key='name')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -683,10 +758,20 @@ class GroupTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template.
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
     def type(cls):
+        """
+        Group type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -695,11 +780,34 @@ class GroupTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_templates(cls):
+        """
+        Nodes instantiated by these templates will be members of the group.
+
+        :type: [:class:`NodeTemplate`]
+        """
         return relationship.many_to_many(cls, 'node_template')
 
     # endregion
 
-    description = Column(Text)
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For GroupTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to GroupTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     @property
     def as_raw(self):
@@ -747,44 +855,14 @@ class GroupTemplateBase(TemplateModelMixin):
 
 class PolicyTemplateBase(TemplateModelMixin):
     """
-    Policies can be applied to zero or more :class:`NodeTemplate` or :class:`GroupTemplate`
-    instances.
-
-    :ivar name: Name (unique for this service template)
-    :vartype name: basestring
-    :ivar type: Policy type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar node_templates: Policy will be enacted on all nodes instantiated by these templates
-    :vartype node_templates: [:class:`NodeTemplate`]
-    :ivar group_templates: Policy will be enacted on all nodes in these groups
-    :vartype group_templates: [:class:`GroupTemplate`]
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar service_template: Containing service template
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar policies: Instantiated policies
-    :vartype policies: [:class:`Policy`]
+    Template for creating a :class:`Policy` instance, which is a typed set of orchestration hints
+    applied to zero or more :class:`Node` or :class:`Group` instances.
     """
 
     __tablename__ = 'policy_template'
 
-    __private_fields__ = ['type_fk', 'service_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For PolicyTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PolicyTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'service_template_fk')
 
     # region association proxies
 
@@ -798,10 +876,20 @@ class PolicyTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def policies(cls):
+        """
+        Instantiated policies.
+
+        :type: [:class:`Policy`]
+        """
         return relationship.one_to_many(cls, 'policy')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -810,10 +898,20 @@ class PolicyTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template.
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
     def type(cls):
+        """
+        Policy type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -822,15 +920,43 @@ class PolicyTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_templates(cls):
+        """
+        Policy will be enacted on all nodes instantiated by these templates.
+
+        :type: {:obj:`basestring`: :class:`NodeTemplate`}
+        """
         return relationship.many_to_many(cls, 'node_template')
 
     @declared_attr
     def group_templates(cls):
+        """
+        Policy will be enacted on all nodes in all groups instantiated by these templates.
+
+        :type: {:obj:`basestring`: :class:`GroupTemplate`}
+        """
         return relationship.many_to_many(cls, 'group_template')
 
     # endregion
 
-    description = Column(Text)
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For PolicyTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to PolicyTemplate"""
+        return relationship.foreign_key('service_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     @property
     def as_raw(self):
@@ -879,30 +1005,13 @@ class PolicyTemplateBase(TemplateModelMixin):
 
 class SubstitutionTemplateBase(TemplateModelMixin):
     """
-    Used to substitute a single node for the entire deployment.
-
-    :ivar node_type: Exposed node type
-    :vartype node_type: :class:`Type`
-    :ivar mappings: Requirement and capability mappings
-    :vartype mappings: {basestring: :class:`SubstitutionTemplateMapping`}
-    :ivar service_template: Containing service template
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar substitutions: Instantiated substitutions
-    :vartype substitutions: [:class:`Substitution`]
+    Template for creating a :class:`Substitution` instance, which exposes an entire instantiated
+    service as a single node.
     """
 
     __tablename__ = 'substitution_template'
 
-    __private_fields__ = ['node_type_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def node_type_fk(cls):
-        """For SubstitutionTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    # endregion
+    __private_fields__ = ('node_type_fk',)
 
     # region association proxies
 
@@ -916,10 +1025,20 @@ class SubstitutionTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def substitutions(cls):
+        """
+        Instantiated substitutions.
+
+        :type: [:class:`Substitution`]
+        """
         return relationship.one_to_many(cls, 'substitution')
 
     @declared_attr
     def mappings(cls):
+        """
+        Map requirement and capabilities to exposed node.
+
+        :type: {:obj:`basestring`: :class:`SubstitutionTemplateMapping`}
+        """
         return relationship.one_to_many(cls, 'substitution_template_mapping', dict_key='name')
 
     # endregion
@@ -928,10 +1047,24 @@ class SubstitutionTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_type(cls):
+        """
+        Exposed node type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def node_type_fk(cls):
+        """For SubstitutionTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -961,52 +1094,20 @@ class SubstitutionTemplateBase(TemplateModelMixin):
 
 class SubstitutionTemplateMappingBase(TemplateModelMixin):
     """
-    Used by :class:`SubstitutionTemplate` to map a capability or a requirement to a node.
-
-    Only one of `capability_template` and `requirement_template` can be set.
-
-    :ivar name: Exposed capability or requirement name
-    :vartype name: basestring
-    :ivar node_template: Node template
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar capability_template: Capability template in the node template
-    :vartype capability_template: :class:`CapabilityTemplate`
-    :ivar requirement_template: Requirement template in the node template
-    :vartype requirement_template: :class:`RequirementTemplate`
-    :ivar substitution_template: Containing substitution template
-    :vartype substitution_template: :class:`SubstitutionTemplate`
+    Used by :class:`SubstitutionTemplate` to map a capability template or a requirement template to
+    the exposed node.
+
+    The :attr:`name` field should match the capability or requirement name on the exposed node's
+    type.
+
+    Only one of :attr:`capability_template` and :attr:`requirement_template` can be set.
     """
 
     __tablename__ = 'substitution_template_mapping'
 
-    __private_fields__ = ['substitution_template_fk',
-                          'node_template_fk',
+    __private_fields__ = ('substitution_template_fk',
                           'capability_template_fk',
-                          'requirement_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def substitution_template_fk(cls):
-        """For SubstitutionTemplate one-to-many to SubstitutionTemplateMapping"""
-        return relationship.foreign_key('substitution_template')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For SubstitutionTemplate one-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template')
-
-    @declared_attr
-    def capability_template_fk(cls):
-        """For SubstitutionTemplate one-to-one to CapabilityTemplate"""
-        return relationship.foreign_key('capability_template', nullable=True)
-
-    @declared_attr
-    def requirement_template_fk(cls):
-        """For SubstitutionTemplate one-to-one to RequirementTemplate"""
-        return relationship.foreign_key('requirement_template', nullable=True)
-
-    # endregion
+                          'requirement_template_fk')
 
     # region association proxies
 
@@ -1015,17 +1116,22 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
     # region one_to_one relationships
 
     @declared_attr
-    def node_template(cls):
-        return relationship.one_to_one(
-            cls, 'node_template', back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
     def capability_template(cls):
+        """
+        Capability template to expose (can be ``None``).
+
+        :type: :class:`CapabilityTemplate`
+        """
         return relationship.one_to_one(
             cls, 'capability_template', back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def requirement_template(cls):
+        """
+        Requirement template to expose (can be ``None``).
+
+        :type: :class:`RequirementTemplate`
+        """
         return relationship.one_to_one(
             cls, 'requirement_template', back_populates=relationship.NO_BACK_POP)
 
@@ -1039,10 +1145,34 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
 
     @declared_attr
     def substitution_template(cls):
+        """
+        Containing substitution template.
+
+        :type: :class:`SubstitutionTemplate`
+        """
         return relationship.many_to_one(cls, 'substitution_template', back_populates='mappings')
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def substitution_template_fk(cls):
+        """For SubstitutionTemplate one-to-many to SubstitutionTemplateMapping"""
+        return relationship.foreign_key('substitution_template')
+
+    @declared_attr
+    def capability_template_fk(cls):
+        """For SubstitutionTemplate one-to-one to CapabilityTemplate"""
+        return relationship.foreign_key('capability_template', nullable=True)
+
+    @declared_attr
+    def requirement_template_fk(cls):
+        """For SubstitutionTemplate one-to-one to RequirementTemplate"""
+        return relationship.foreign_key('requirement_template', nullable=True)
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1054,7 +1184,11 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
     def instantiate(self, container):
         from . import models
         context = ConsumptionContext.get_thread_local()
-        nodes = self.node_template.nodes
+        if self.capability_template is not None:
+            node_template = self.capability_template.node_template
+        else:
+            node_template = self.requirement_template.node_template
+        nodes = node_template.nodes
         if len(nodes) == 0:
             context.validation.report(
                 'mapping "{0}" refers to node template "{1}" but there are no '
@@ -1070,9 +1204,10 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
                 if a_capability.capability_template.name == self.capability_template.name:
                     capability = a_capability
         return models.SubstitutionMapping(name=self.name,
-                                          node=node,
                                           capability=capability,
-                                          requirement_template=self.requirement_template)
+                                          requirement_template=self.requirement_template,
+                                          node=node)
+
 
     def validate(self):
         context = ConsumptionContext.get_thread_local()
@@ -1085,9 +1220,13 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
 
     def dump(self):
         context = ConsumptionContext.get_thread_local()
+        if self.capability_template is not None:
+            node_template = self.capability_template.node_template
+        else:
+            node_template = self.requirement_template.node_template
         console.puts('{0} -> {1}.{2}'.format(
             context.style.node(self.name),
-            context.style.node(self.node_template.name),
+            context.style.node(node_template.name),
             context.style.node(self.capability_template.name
                                if self.capability_template
                                else self.requirement_template.name)))
@@ -1095,70 +1234,26 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
 
 class RequirementTemplateBase(TemplateModelMixin):
     """
-    A requirement for a :class:`NodeTemplate`. During instantiation will be matched with a
-    capability of another node.
-
-    Requirements may optionally contain a :class:`RelationshipTemplate` that will be created between
-    the nodes.
-
-    :ivar name: Name (a node template can have multiple requirements with the same name)
-    :vartype name: basestring
-    :ivar target_node_type: Required node type (optional)
-    :vartype target_node_type: :class:`Type`
-    :ivar target_node_template: Required node template (optional)
-    :vartype target_node_template: :class:`NodeTemplate`
-    :ivar target_capability_type: Required capability type (optional)
-    :vartype target_capability_type: :class:`Type`
-    :ivar target_capability_name: Name of capability in target node (optional)
-    :vartype target_capability_name: basestring
-    :ivar target_node_template_constraints: Constraints for filtering relationship targets
-    :vartype target_node_template_constraints: [:class:`NodeTemplateConstraint`]
-    :ivar relationship_template: Template for relationships (optional)
-    :vartype relationship_template: :class:`RelationshipTemplate`
-    :ivar node_template: Containing node template
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar substitution_template_mapping: Our contribution to service substitution
-    :vartype substitution_template_mapping: :class:`SubstitutionTemplateMapping`
-    :ivar substitution_mapping: Our contribution to service substitution
-    :vartype substitution_mapping: :class:`SubstitutionMapping`
-    """
+    Template for creating :class:`Relationship` instances, which are optionally-typed edges in the
+    service topology, connecting a :class:`Node` to a :class:`Capability` of another node.
 
-    __tablename__ = 'requirement_template'
+    Note that there is no equivalent "Requirement" instance model. Instead, during instantiation a
+    requirement template is matched with a capability and a :class:`Relationship` is instantiated.
 
-    __private_fields__ = ['target_node_type_fk',
-                          'target_node_template_fk',
-                          'target_capability_type_fk'
-                          'node_template_fk',
-                          'relationship_template_fk']
+    A requirement template *must* target a :class:`CapabilityType` or a capability name. It can
+    optionally target a specific :class:`NodeType` or :class:`NodeTemplate`.
 
-    # region foreign keys
-
-    @declared_attr
-    def target_node_type_fk(cls):
-        """For RequirementTemplate many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def target_node_template_fk(cls):
-        """For RequirementTemplate one-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    @declared_attr
-    def target_capability_type_fk(cls):
-        """For RequirementTemplate one-to-one to NodeTemplate"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to RequirementTemplate"""
-        return relationship.foreign_key('node_template')
+    Requirement templates may optionally contain a :class:`RelationshipTemplate`. If they do not,
+    a :class:`Relationship` will be instantiated with default values.
+    """
 
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For RequirementTemplate one-to-one to RelationshipTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
+    __tablename__ = 'requirement_template'
 
-    # endregion
+    __private_fields__ = ('target_capability_type_fk',
+                          'target_node_template_fk',
+                          'target_node_type_fk',
+                          'relationship_template_fk',
+                          'node_template_fk')
 
     # region association proxies
 
@@ -1167,21 +1262,36 @@ class RequirementTemplateBase(TemplateModelMixin):
     # region one_to_one relationships
 
     @declared_attr
-    def target_node_template(cls):
+    def target_capability_type(cls):
+        """
+        Target capability type.
+
+        :type: :class:`CapabilityType`
+        """
         return relationship.one_to_one(cls,
-                                       'node_template',
-                                       fk='target_node_template_fk',
+                                       'type',
+                                       fk='target_capability_type_fk',
                                        back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
-    def target_capability_type(cls):
+    def target_node_template(cls):
+        """
+        Target node template (can be ``None``).
+
+        :type: :class:`NodeTemplate`
+        """
         return relationship.one_to_one(cls,
-                                       'type',
-                                       fk='target_capability_type_fk',
+                                       'node_template',
+                                       fk='target_node_template_fk',
                                        back_populates=relationship.NO_BACK_POP)
 
     @declared_attr
     def relationship_template(cls):
+        """
+        Associated relationship template (can be ``None``).
+
+        :type: :class:`RelationshipTemplate`
+        """
         return relationship.one_to_one(cls, 'relationship_template')
 
     # endregion
@@ -1190,6 +1300,11 @@ class RequirementTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def relationships(cls):
+        """
+        Instantiated relationships.
+
+        :type: [:class:`Relationship`]
+        """
         return relationship.one_to_many(cls, 'relationship')
 
     # endregion
@@ -1198,17 +1313,65 @@ class RequirementTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_template(cls):
+        """
+        Containing node template.
+
+        :type: :class:`NodeTemplate`
+        """
         return relationship.many_to_one(cls, 'node_template', fk='node_template_fk')
 
     @declared_attr
     def target_node_type(cls):
+        """
+        Target node type (can be ``None``).
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(
             cls, 'type', fk='target_node_type_fk', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    target_capability_name = Column(Text)
-    target_node_template_constraints = Column(PickleType)
+    # region foreign keys
+
+    @declared_attr
+    def target_node_type_fk(cls):
+        """For RequirementTemplate many-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def target_node_template_fk(cls):
+        """For RequirementTemplate one-to-one to NodeTemplate"""
+        return relationship.foreign_key('node_template', nullable=True)
+
+    @declared_attr
+    def target_capability_type_fk(cls):
+        """For RequirementTemplate one-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    @declared_attr
+    def node_template_fk(cls):
+        """For NodeTemplate one-to-many to RequirementTemplate"""
+        return relationship.foreign_key('node_template')
+
+    @declared_attr
+    def relationship_template_fk(cls):
+        """For RequirementTemplate one-to-one to RelationshipTemplate"""
+        return relationship.foreign_key('relationship_template', nullable=True)
+
+    # endregion
+
+    target_capability_name = Column(Text, doc="""
+    Target capability name in node template or node type (can be ``None``).
+
+    :type: :obj:`basestring`
+    """)
+
+    target_node_template_constraints = Column(PickleType, doc="""
+    Constraints for filtering relationship targets.
+
+    :type: [:class:`NodeTemplateConstraint`]
+    """)
 
     def find_target(self, source_node_template):
         context = ConsumptionContext.get_thread_local()
@@ -1313,41 +1476,16 @@ class RequirementTemplateBase(TemplateModelMixin):
 
 class RelationshipTemplateBase(TemplateModelMixin):
     """
-    Optional addition to a :class:`RequirementTemplate` in :class:`NodeTemplate` that can be applied
-    when the requirement is matched with a capability.
-
-    Note that a relationship template here is not equivalent to a relationship template entity in
-    TOSCA. For example, a TOSCA requirement specifying a relationship type instead of a template
-    would still be represented here as a relationship template.
-
-    :ivar name: Name (optional; if present is unique for this service template)
-    :vartype name: basestring
-    :ivar type: Relationship type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar interface_templates: Bundles of operations
-    :vartype interface_templates: {basestring: :class:`InterfaceTemplate`}
-    :ivar requirement_template: Containing requirement template
-    :vartype requirement_template: :class:`RequirementTemplate`
-    :ivar relationships: Instantiated relationships
-    :vartype relationships: [:class:`Relationship`]
+    Optional addition to a :class:`RequirementTemplate`.
+
+    Note that a relationship template here is not exactly equivalent to a relationship template
+    entity in TOSCA. For example, a TOSCA requirement specifying a relationship type rather than a
+    relationship template would still be represented here as a relationship template.
     """
 
     __tablename__ = 'relationship_template'
 
-    __private_fields__ = ['type_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For RelationshipTemplate many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    # endregion
+    __private_fields__ = ('type_fk',)
 
     # region association proxies
 
@@ -1361,14 +1499,29 @@ class RelationshipTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def relationships(cls):
+        """
+        Instantiated relationships.
+
+        :type: [:class:`Relationship`]
+        """
         return relationship.one_to_many(cls, 'relationship')
 
     @declared_attr
     def interface_templates(cls):
+        """
+        Associated interface templates.
+
+        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+        """
         return relationship.one_to_many(cls, 'interface_template', dict_key='name')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -1377,11 +1530,29 @@ class RelationshipTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def type(cls):
+        """
+        Relationship type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    description = Column(Text)
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For RelationshipTemplate many-to-one to Type"""
+        return relationship.foreign_key('type', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     @property
     def as_raw(self):
@@ -1426,50 +1597,15 @@ class RelationshipTemplateBase(TemplateModelMixin):
 
 class CapabilityTemplateBase(TemplateModelMixin):
     """
-    A capability of a :class:`NodeTemplate`. Nodes expose zero or more capabilities that can be
-    matched with :class:`Requirement` instances of other nodes.
-
-    :ivar name: Name (unique for the node template)
-    :vartype name: basestring
-    :ivar type: Capability type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar valid_source_node_types: Reject requirements that are not from these node types (optional)
-    :vartype valid_source_node_types: [:class:`Type`]
-    :ivar min_occurrences: Minimum number of requirement matches required
-    :vartype min_occurrences: int
-    :ivar max_occurrences: Maximum number of requirement matches allowed
-    :vartype min_occurrences: int
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar node_template: Containing node template
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar substitution_template_mapping: Our contribution to service substitution
-    :vartype substitution_template_mapping: :class:`SubstitutionTemplateMapping`
-    :ivar capabilities: Instantiated capabilities
-    :vartype capabilities: [:class:`Capability`]
+    Template for creating :class:`Capability` instances, typed attachments which serve two purposes:
+    to provide extra properties and attributes to :class:`Node` instances, and to expose targets for
+    :class:`Relationship` instances from other nodes.
     """
 
     __tablename__ = 'capability_template'
 
-    __private_fields__ = ['type_fk',
-                          'node_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For CapabilityTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to CapabilityTemplate"""
-        return relationship.foreign_key('node_template')
-
-    # endregion
-
+    __private_fields__ = ('type_fk',
+                          'node_template_fk')
 
     # region association proxies
 
@@ -1483,10 +1619,20 @@ class CapabilityTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def capabilities(cls):
+        """
+        Instantiated capabilities.
+
+        :type: [:class:`Capability`]
+        """
         return relationship.one_to_many(cls, 'capability')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -1495,10 +1641,20 @@ class CapabilityTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_template(cls):
+        """
+        Containing node template.
+
+        :type: :class:`NodeTemplate`
+        """
         return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
     def type(cls):
+        """
+        Capability type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
@@ -1507,13 +1663,46 @@ class CapabilityTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def valid_source_node_types(cls):
+        """
+        Reject requirements that are not from these node types.
+
+        :type: [:class:`Type`]
+        """
         return relationship.many_to_many(cls, 'type', prefix='valid_sources')
 
     # endregion
 
-    description = Column(Text)
-    min_occurrences = Column(Integer, default=None)  # optional
-    max_occurrences = Column(Integer, default=None)  # optional
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For CapabilityTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_template_fk(cls):
+        """For NodeTemplate one-to-many to CapabilityTemplate"""
+        return relationship.foreign_key('node_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    min_occurrences = Column(Integer, default=None, doc="""
+    Minimum number of requirement matches required.
+
+    :type: :obj:`int`
+    """)
+
+    max_occurrences = Column(Integer, default=None, doc="""
+    Maximum number of requirement matches allowed.
+
+    :type: :obj:`int`
+    """)
 
     def satisfies_requirement(self,
                               source_node_template,
@@ -1588,58 +1777,19 @@ class CapabilityTemplateBase(TemplateModelMixin):
 
 class InterfaceTemplateBase(TemplateModelMixin):
     """
-    A typed set of :class:`OperationTemplate`.
-
-    :ivar name: Name (unique for the node, group, or relationship template)
-    :vartype name: basestring
-    :ivar type: Interface type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar inputs: Inputs that can be used by all operations in the interface
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar operation_templates: Operations
-    :vartype operation_templates: {basestring: :class:`OperationTemplate`}
-    :ivar node_template: Containing node template
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar group_template: Containing group template
-    :vartype group_template: :class:`GroupTemplate`
-    :ivar relationship_template: Containing relationship template
-    :vartype relationship_template: :class:`RelationshipTemplate`
-    :ivar interfaces: Instantiated interfaces
-    :vartype interfaces: [:class:`Interface`]
+    Template for creating :class:`Interface` instances, which are typed bundles of
+    :class:`Operation` instances.
+
+    Can be associated with a :class:`NodeTemplate`, a :class:`GroupTemplate`, or a
+    :class:`RelationshipTemplate`.
     """
 
     __tablename__ = 'interface_template'
 
-    __private_fields__ = ['type_fk',
+    __private_fields__ = ('type_fk',
                           'node_template_fk',
                           'group_template_fk',
-                          'relationship_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For InterfaceTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    @declared_attr
-    def group_template_fk(cls):
-        """For GroupTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('group_template', nullable=True)
-
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For RelationshipTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
-
-    # endregion
+                          'relationship_template_fk')
 
     # region association proxies
 
@@ -1653,14 +1803,30 @@ class InterfaceTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def inputs(cls):
+        """
+        Declarations for externally provided parameters that can be used by all operations of the
+        interface.
+
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
         return relationship.one_to_many(cls, 'input', dict_key='name')
 
     @declared_attr
     def interfaces(cls):
+        """
+        Instantiated interfaces.
+
+        :type: [:class:`Interface`]
+        """
         return relationship.one_to_many(cls, 'interface')
 
     @declared_attr
     def operation_templates(cls):
+        """
+        Associated operation templates.
+
+        :type: {:obj:`basestring`: :class:`OperationTemplate`}
+        """
         return relationship.one_to_many(cls, 'operation_template', dict_key='name')
 
     # endregion
@@ -1668,24 +1834,72 @@ class InterfaceTemplateBase(TemplateModelMixin):
     # region many_to_one relationships
 
     @declared_attr
-    def relationship_template(cls):
-        return relationship.many_to_one(cls, 'relationship_template')
+    def node_template(cls):
+        """
+        Containing node template (can be ``None``).
+
+        :type: :class:`NodeTemplate`
+        """
+        return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
     def group_template(cls):
+        """
+        Containing group template (can be ``None``).
+
+        :type: :class:`GroupTemplate`
+        """
         return relationship.many_to_one(cls, 'group_template')
 
     @declared_attr
-    def node_template(cls):
-        return relationship.many_to_one(cls, 'node_template')
+    def relationship_template(cls):
+        """
+        Containing relationship template (can be ``None``).
+
+        :type: :class:`RelationshipTemplate`
+        """
+        return relationship.many_to_one(cls, 'relationship_template')
 
     @declared_attr
     def type(cls):
+        """
+        Interface type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    description = Column(Text)
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For InterfaceTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_template_fk(cls):
+        """For NodeTemplate one-to-many to InterfaceTemplate"""
+        return relationship.foreign_key('node_template', nullable=True)
+
+    @declared_attr
+    def group_template_fk(cls):
+        """For GroupTemplate one-to-many to InterfaceTemplate"""
+        return relationship.foreign_key('group_template', nullable=True)
+
+    @declared_attr
+    def relationship_template_fk(cls):
+        """For RelationshipTemplate one-to-many to InterfaceTemplate"""
+        return relationship.foreign_key('relationship_template', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
 
     @property
     def as_raw(self):
@@ -1728,68 +1942,15 @@ class InterfaceTemplateBase(TemplateModelMixin):
 
 class OperationTemplateBase(TemplateModelMixin):
     """
-    An operation in a :class:`InterfaceTemplate`.
-
-    Operations are executed by an associated :class:`PluginSpecification` via an executor.
-
-    :ivar name: Name (unique for the interface or service template)
-    :vartype name: basestring
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar relationship_edge: When true specified that the operation is on the relationship's
-                             target edge instead of its source (only used by relationship
-                             operations)
-    :vartype relationship_edge: bool
-    :ivar implementation: Implementation (interpreted by the plugin)
-    :vartype implementation: basestring
-    :ivar dependencies: Dependency strings (interpreted by the plugin)
-    :vartype dependencies: [basestring]
-    :ivar inputs: Inputs that can be used by this operation
-    :vartype inputs: {basestring: :class:`Input`}
-    :ivar plugin_specification: Associated plugin
-    :vartype plugin_specification: :class:`PluginSpecification`
-    :ivar configurations: Configuration (interpreted by the plugin)
-    :vartype configurations: {basestring, :class:`Configuration`}
-    :ivar function: Name of the operation function
-    :vartype function: basestring
-    :ivar executor: Name of executor to run the operation with
-    :vartype executor: basestring
-    :ivar max_attempts: Maximum number of attempts allowed in case of failure
-    :vartype max_attempts: int
-    :ivar retry_interval: Interval between retries (in seconds)
-    :vartype retry_interval: int
-    :ivar interface_template: Containing interface template
-    :vartype interface_template: :class:`InterfaceTemplate`
-    :ivar service_template: Containing service template
-    :vartype service_template: :class:`ServiceTemplate`
-    :ivar operations: Instantiated operations
-    :vartype operations: [:class:`Operation`]
+    Template for creating :class:`Operation` instances, which are entry points to Python functions
+    called as part of a workflow execution.
     """
 
     __tablename__ = 'operation_template'
 
-    __private_fields__ = ['service_template_fk',
+    __private_fields__ = ('service_template_fk',
                           'interface_template_fk',
-                          'plugin_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to OperationTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    @declared_attr
-    def interface_template_fk(cls):
-        """For InterfaceTemplate one-to-many to OperationTemplate"""
-        return relationship.foreign_key('interface_template', nullable=True)
-
-    @declared_attr
-    def plugin_specification_fk(cls):
-        """For OperationTemplate one-to-one to PluginSpecification"""
-        return relationship.foreign_key('plugin_specification', nullable=True)
-
-    # endregion
+                          'plugin_fk')
 
     # region association proxies
 
@@ -1799,6 +1960,11 @@ class OperationTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def plugin_specification(cls):
+        """
+        Associated plugin specification.
+
+        :type: :class:`PluginSpecification`
+        """
         return relationship.one_to_one(
             cls, 'plugin_specification', back_populates=relationship.NO_BACK_POP)
 
@@ -1807,15 +1973,30 @@ class OperationTemplateBase(TemplateModelMixin):
     # region one_to_many relationships
 
     @declared_attr
-    def inputs(cls):
-        return relationship.one_to_many(cls, 'input', dict_key='name')
-
-    @declared_attr
     def operations(cls):
+        """
+        Instantiated operations.
+
+        :type: [:class:`Operation`]
+        """
         return relationship.one_to_many(cls, 'operation')
 
     @declared_attr
+    def inputs(cls):
+        """
+        Declarations for parameters provided to the :attr:`implementation`.
+
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
+        return relationship.one_to_many(cls, 'input', dict_key='name')
+
+    @declared_attr
     def configurations(cls):
+        """
+        Configuration parameters for the operation instance Python :attr:`function`.
+
+        :type: {:obj:`basestring`: :class:`Configuration`}
+        """
         return relationship.one_to_many(cls, 'configuration', dict_key='name')
 
     # endregion
@@ -1824,11 +2005,21 @@ class OperationTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template (can be ``None``). For workflow operation templates.
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template',
                                         back_populates='workflow_templates')
 
     @declared_attr
     def interface_template(cls):
+        """
+        Containing interface template (can be ``None``).
+
+        :type: :class:`InterfaceTemplate`
+        """
         return relationship.many_to_one(cls, 'interface_template')
 
     # endregion
@@ -1837,14 +2028,73 @@ class OperationTemplateBase(TemplateModelMixin):
 
     # endregion
 
-    description = Column(Text)
-    relationship_edge = Column(Boolean)
-    implementation = Column(Text)
-    dependencies = Column(modeling_types.StrictList(item_cls=basestring))
-    function = Column(Text)
-    executor = Column(Text)
-    max_attempts = Column(Integer)
-    retry_interval = Column(Integer)
+    # region foreign keys
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to OperationTemplate"""
+        return relationship.foreign_key('service_template', nullable=True)
+
+    @declared_attr
+    def interface_template_fk(cls):
+        """For InterfaceTemplate one-to-many to OperationTemplate"""
+        return relationship.foreign_key('interface_template', nullable=True)
+
+    @declared_attr
+    def plugin_specification_fk(cls):
+        """For OperationTemplate one-to-one to PluginSpecification"""
+        return relationship.foreign_key('plugin_specification', nullable=True)
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    relationship_edge = Column(Boolean, doc="""
+    When ``True`` specifies that the operation is on the relationship's target edge; ``False`` is
+    the source edge (only used by operations on relationships)
+
+    :type: :obj:`bool`
+    """)
+
+    implementation = Column(Text, doc="""
+    Implementation (usually the name of an artifact).
+
+    :type: :obj:`basestring`
+    """)
+
+    dependencies = Column(modeling_types.StrictList(item_cls=basestring), doc="""
+    Dependencies (usually names of artifacts).
+
+    :type: [:obj:`basestring`]
+    """)
+
+    function = Column(Text, doc="""
+    Full path to Python function.
+
+    :type: :obj:`basestring`
+    """)
+
+    executor = Column(Text, doc="""
+    Name of executor.
+
+    :type: :obj:`basestring`
+    """)
+
+    max_attempts = Column(Integer, doc="""
+    Maximum number of attempts allowed in case of task failure.
+
+    :type: :obj:`int`
+    """)
+
+    retry_interval = Column(Integer, doc="""
+    Interval between task retry attemps (in seconds).
+
+    :type: :obj:`float`
+    """)
 
     @property
     def as_raw(self):
@@ -1917,48 +2167,14 @@ class OperationTemplateBase(TemplateModelMixin):
 
 class ArtifactTemplateBase(TemplateModelMixin):
     """
-    A file associated with a :class:`NodeTemplate`.
-
-    :ivar name: Name (unique for the node template)
-    :vartype name: basestring
-    :ivar type: Artifact type
-    :vartype type: :class:`Type`
-    :ivar description: Human-readable description
-    :vartype description: basestring
-    :ivar source_path: Source path (CSAR or repository)
-    :vartype source_path: basestring
-    :ivar target_path: Path at destination machine
-    :vartype target_path: basestring
-    :ivar repository_url: Repository URL
-    :vartype repository_path: basestring
-    :ivar repository_credential: Credentials for accessing the repository
-    :vartype repository_credential: {basestring: basestring}
-    :ivar properties: Associated parameters
-    :vartype properties: {basestring: :class:`Property`}
-    :ivar node_template: Containing node template
-    :vartype node_template: :class:`NodeTemplate`
-    :ivar artifacts: Instantiated artifacts
-    :vartype artifacts: [:class:`Artifact`]
+    Template for creating an :class:`Artifact` instance, which is a typed file, either provided in a
+    CSAR or downloaded from a repository.
     """
 
     __tablename__ = 'artifact_template'
 
-    __private_fields__ = ['type_fk',
-                          'node_template_fk']
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For ArtifactTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to ArtifactTemplate"""
-        return relationship.foreign_key('node_template')
-
-    # endregion
+    __private_fields__ = ('type_fk',
+                          'node_template_fk')
 
     # region association proxies
 
@@ -1972,10 +2188,20 @@ class ArtifactTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def artifacts(cls):
+        """
+        Instantiated artifacts.
+
+        :type: [:class:`Artifact`]
+        """
         return relationship.one_to_many(cls, 'artifact')
 
     @declared_attr
     def properties(cls):
+        """
+        Declarations for associated immutable parameters.
+
+        :type: {:obj:`basestring`: :class:`Property`}
+        """
         return relationship.one_to_many(cls, 'property', dict_key='name')
 
     # endregion
@@ -1984,19 +2210,67 @@ class ArtifactTemplateBase(TemplateModelMixin):
 
     @declared_attr
     def node_template(cls):
+        """
+        Containing node template.
+
+        :type: :class:`NodeTemplate`
+        """
         return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
     def type(cls):
+        """
+        Artifact type.
+
+        :type: :class:`Type`
+        """
         return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
-    description = Column(Text)
-    source_path = Column(Text)
-    target_path = Column(Text)
-    repository_url = Column(Text)
-    repository_credential = Column(modeling_types.StrictDict(basestring, basestring))
+    # region foreign keys
+
+    @declared_attr
+    def type_fk(cls):
+        """For ArtifactTemplate many-to-one to Type"""
+        return relationship.foreign_key('type')
+
+    @declared_attr
+    def node_template_fk(cls):
+        """For NodeTemplate one-to-many to ArtifactTemplate"""
+        return relationship.foreign_key('node_template')
+
+    # endregion
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
+    source_path = Column(Text, doc="""
+    Source path (in CSAR or repository).
+
+    :type: :obj:`basestring`
+    """)
+
+    target_path = Column(Text, doc="""
+    Path at which to install at destination.
+
+    :type: :obj:`basestring`
+    """)
+
+    repository_url = Column(Text, doc="""
+    Repository URL.
+
+    :type: :obj:`basestring`
+    """)
+
+    repository_credential = Column(modeling_types.StrictDict(basestring, basestring), doc="""
+    Credentials for accessing the repository.
+
+    :type: {:obj:`basestring`, :obj:`basestring`}
+    """)
 
     @property
     def as_raw(self):
@@ -2050,52 +2324,64 @@ class ArtifactTemplateBase(TemplateModelMixin):
 
 class PluginSpecificationBase(TemplateModelMixin):
     """
-    Plugin specification.
-
-    :ivar name: Required plugin name
-    :vartype name: basestring
-    :ivar version: Minimum plugin version
-    :vartype version: basestring
-    :ivar enabled: Whether the plugin is enabled
-    :vartype enabled: bool
-    :ivar plugin: The matching plugin (or None if not matched)
-    :vartype plugin: :class:`Plugin`
+    Requirement for a :class:`Plugin`.
+
+    The actual plugin to be selected depends on those currently installed in ARIA.
     """
 
     __tablename__ = 'plugin_specification'
 
-    __private_fields__ = ['service_template_fk',
-                          'plugin_fk']
+    __private_fields__ = ('service_template_fk',
+                          'plugin_fk')
 
-    version = Column(Text)
-    enabled = Column(Boolean, nullable=False, default=True)
+    version = Column(Text, doc="""
+    Minimum plugin version.
 
-    # region foreign keys
+    :type: :obj:`basestring`
+    """)
 
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PluginSpecification"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    @declared_attr
-    def plugin_fk(cls):
-        """For PluginSpecification many-to-one to Plugin"""
-        return relationship.foreign_key('plugin', nullable=True)
+    enabled = Column(Boolean, nullable=False, default=True, doc="""
+    Whether the plugin is enabled.
 
-    # endregion
+    :type: :obj:`bool`
+    """)
 
     # region many_to_one relationships
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template.
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
     def plugin(cls): # pylint: disable=method-hidden
+        """
+        Matched plugin.
+
+        :type: :class:`Plugin`
+        """
         return relationship.many_to_one(cls, 'plugin', back_populates=relationship.NO_BACK_POP)
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to PluginSpecification"""
+        return relationship.foreign_key('service_template', nullable=True)
+
+    @declared_attr
+    def plugin_fk(cls):
+        """For PluginSpecification many-to-one to Plugin"""
+        return relationship.foreign_key('plugin', nullable=True)
+
+    # endregion
+
     @property
     def as_raw(self):
         return collections.OrderedDict((

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/types.py
----------------------------------------------------------------------
diff --git a/aria/modeling/types.py b/aria/modeling/types.py
index 920a0c2..c34326e 100644
--- a/aria/modeling/types.py
+++ b/aria/modeling/types.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Allows JSON-serializable collections to be used as SQLAlchemy column types.
+"""
+
 import json
 from collections import namedtuple
 
@@ -52,12 +56,18 @@ class _MutableType(TypeDecorator):
 
 
 class Dict(_MutableType):
+    """
+    JSON-serializable dict type for SQLAlchemy columns.
+    """
     @property
     def python_type(self):
         return dict
 
 
 class List(_MutableType):
+    """
+    JSON-serializable list type for SQLAlchemy columns.
+    """
     @property
     def python_type(self):
         return list
@@ -67,7 +77,9 @@ class _StrictDictMixin(object):
 
     @classmethod
     def coerce(cls, key, value):
-        "Convert plain dictionaries to MutableDict."
+        """
+        Convert plain dictionaries to MutableDict.
+        """
         try:
             if not isinstance(value, cls):
                 if isinstance(value, dict):
@@ -117,7 +129,9 @@ class _MutableDict(mutable.MutableDict):
 
     @classmethod
     def coerce(cls, key, value):
-        "Convert plain dictionaries to MutableDict."
+        """
+        Convert plain dictionaries to MutableDict.
+        """
         try:
             return mutable.MutableDict.coerce(key, value)
         except ValueError as e:
@@ -142,7 +156,9 @@ class _StrictListMixin(object):
             raise exceptions.ValueFormatException('could not coerce to MutableDict', cause=e)
 
     def __setitem__(self, index, value):
-        """Detect list set events and emit change events."""
+        """
+        Detect list set events and emit change events.
+        """
         self._assert_item(value)
         super(_StrictListMixin, self).__setitem__(index, value)
 
@@ -169,7 +185,9 @@ class _MutableList(mutable.MutableList):
 
     @classmethod
     def coerce(cls, key, value):
-        "Convert plain dictionaries to MutableDict."
+        """
+        Convert plain dictionaries to MutableDict.
+        """
         try:
             return mutable.MutableList.coerce(key, value)
         except ValueError as e:
@@ -181,9 +199,9 @@ _StrictValue = namedtuple('_StrictValue', 'type_cls, listener_cls')
 
 class _StrictDict(object):
     """
-    This entire class functions as a factory for strict dicts and their listeners.
-    No type class, and no listener type class is created more than once. If a relevant type class
-    exists it is returned.
+    This entire class functions as a factory for strict dicts and their listeners. No type class,
+    and no listener type class is created more than once. If a relevant type class exists it is
+    returned.
     """
     _strict_map = {}
 
@@ -216,13 +234,19 @@ class _StrictDict(object):
 
 
 StrictDict = _StrictDict()
+"""
+JSON-serializable strict dict type for SQLAlchemy columns.
+
+:param key_cls:
+:param value_cls:
+"""
 
 
 class _StrictList(object):
     """
-    This entire class functions as a factory for strict lists and their listeners.
-    No type class, and no listener type class is created more than once. If a relevant type class
-    exists it is returned.
+    This entire class functions as a factory for strict lists and their listeners. No type class,
+    and no listener type class is created more than once. If a relevant type class exists it is
+    returned.
     """
     _strict_map = {}
 
@@ -254,6 +278,11 @@ class _StrictList(object):
 
 
 StrictList = _StrictList()
+"""
+JSON-serializable strict list type for SQLAlchemy columns.
+
+:param item_cls:
+"""
 
 
 def _mutable_association_listener(mapper, cls):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index 43be410..5193cd9 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Miscellaneous modeling utilities.
+"""
+
 import os
 from json import JSONEncoder
 from StringIO import StringIO
@@ -26,6 +30,13 @@ from ..utils.formatting import string_list_as_string
 
 
 class ModelJSONEncoder(JSONEncoder):
+    """
+    JSON encoder that automatically unwraps ``value`` attributes.
+    """
+    def __init__(self, *args, **kwargs):
+        # Just here to make sure Sphinx doesn't grab the base constructor's docstring
+        super(ModelJSONEncoder, self).__init__(*args, **kwargs)
+
     def default(self, o):  # pylint: disable=method-hidden
         from .mixins import ModelMixin
         if isinstance(o, ModelMixin):
@@ -40,8 +51,8 @@ class ModelJSONEncoder(JSONEncoder):
 
 class NodeTemplateContainerHolder(object):
     """
-    Wrapper that allows using a :class:`aria.modeling.models.NodeTemplate` model directly as the
-    ``container_holder`` input for :func:`aria.modeling.functions.evaluate`.
+    Wrapper that allows using a :class:`~aria.modeling.models.NodeTemplate` model directly as the
+    ``container_holder`` input for :func:`~aria.modeling.functions.evaluate`.
     """
 
     def __init__(self, node_template):
@@ -60,18 +71,17 @@ def merge_parameter_values(parameter_values, declared_parameters, model_cls):
     Exceptions will be raised for validation errors.
 
     :param parameter_values: provided parameter values or None
-    :type parameter_values: {basestring, object}
+    :type parameter_values: {:obj:`basestring`: object}
     :param declared_parameters: declared parameters
-    :type declared_parameters: {basestring, :class:`aria.modeling.models.Parameter`}
+    :type declared_parameters: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
     :return: the merged parameters
-    :rtype: {basestring, :class:`aria.modeling.models.Parameter`}
-    :raises aria.modeling.exceptions.UndeclaredParametersException: if a key in ``parameter_values``
-            does not exist in ``declared_parameters``
-    :raises aria.modeling.exceptions.MissingRequiredParametersException: if a key in
-            ``declared_parameters`` does not exist in ``parameter_values`` and also has no default
-            value
-    :raises aria.modeling.exceptions.ParametersOfWrongTypeException: if a value in
-            ``parameter_values`` does not match its type in ``declared_parameters``
+    :rtype: {:obj:`basestring`: :class:`~aria.modeling.models.Parameter`}
+    :raises ~aria.modeling.exceptions.UndeclaredParametersException: if a key in
+     ``parameter_values`` does not exist in ``declared_parameters``
+    :raises ~aria.modeling.exceptions.MissingRequiredParametersException: if a key in
+     ``declared_parameters`` does not exist in ``parameter_values`` and also has no default value
+    :raises ~aria.modeling.exceptions.ParametersOfWrongTypeException: if a value in
+      ``parameter_values`` does not match its type in ``declared_parameters``
     """
 
     parameter_values = parameter_values or {}
@@ -204,6 +214,22 @@ def dump_interfaces(interfaces, name='Interfaces'):
 class classproperty(object):                                                                        # pylint: disable=invalid-name
     def __init__(self, f):
         self._func = f
+        self.__doct__ = f.__doc__
 
     def __get__(self, instance, owner):
         return self._func(owner)
+
+
+def fix_doc(cls):
+    """
+    Class decorator to use the last base class's docstring and make sure Sphinx doesn't grab the
+    base constructor's docstring.
+    """
+    original_init = cls.__init__
+    def init(*args, **kwargs):
+        original_init(*args, **kwargs)
+
+    cls.__init__ = init
+    cls.__doc__ = cls.__bases__[-1].__doc__
+
+    return cls

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/__init__.py b/aria/orchestrator/__init__.py
index b855aed..24fee9e 100644
--- a/aria/orchestrator/__init__.py
+++ b/aria/orchestrator/__init__.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-ARIA orchestrator
+Orchestrator package.
 """
+
 from .decorators import (
     workflow,
     operation,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/__init__.py b/aria/orchestrator/context/__init__.py
index ad89b13..a87828d 100644
--- a/aria/orchestrator/context/__init__.py
+++ b/aria/orchestrator/context/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Provides contexts to workflow and operation
+Contexts for workflows and operations.
 """
 
 from . import workflow, operation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index f4df317..f400142 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -14,8 +14,9 @@
 # limitations under the License.
 
 """
-A common context for both workflow and operation
+Common code for contexts.
 """
+
 import logging
 from contextlib import contextmanager
 from functools import partial
@@ -33,7 +34,7 @@ from ...utils.uuid import generate_uuid
 
 class BaseContext(object):
     """
-    Base context object for workflow and operation
+    Base class for contexts.
     """
 
     INSTRUMENTATION_FIELDS = (
@@ -109,52 +110,48 @@ class BaseContext(object):
     @property
     def model(self):
         """
-        Access to the model storage
-        :return:
+        Storage model API ("MAPI").
         """
         return self._model
 
     @property
     def resource(self):
         """
-        Access to the resource storage
-        :return:
+        Storage resource API ("RAPI").
         """
         return self._resource
 
     @property
     def service_template(self):
         """
-        The blueprint model
+        Service template model.
         """
         return self.service.service_template
 
     @property
     def service(self):
         """
-        The deployment model
+        Service instance model.
         """
         return self.model.service.get(self._service_id)
 
     @property
     def name(self):
         """
-        The operation name
-        :return:
+        Operation name.
         """
         return self._name
 
     @property
     def id(self):
         """
-        The operation id
-        :return:
+        Operation ID.
         """
         return self._id
 
     def download_resource(self, destination, path=None):
         """
-        Download a blueprint resource from the resource storage
+        Download a service template resource from the storage resource API ("RAPI").
         """
         try:
             self.resource.service.download(entry_id=str(self.service.id),
@@ -167,9 +164,9 @@ class BaseContext(object):
 
     def download_resource_and_render(self, destination, path=None, variables=None):
         """
-        Download a blueprint resource from the resource storage render its content as a jinja
-        template using the provided variables. ctx is available to the template without providing it
-        explicitly.
+        Downloads a service template resource from the resource storage and renders its content as a
+        Jinja template using the provided variables. ``ctx`` is available to the template without
+        providing it explicitly.
         """
         resource_content = self.get_resource(path=path)
         resource_content = self._render_resource(resource_content=resource_content,
@@ -179,7 +176,7 @@ class BaseContext(object):
 
     def get_resource(self, path=None):
         """
-        Read a deployment resource as string from the resource storage
+        Reads a service instance resource as string from the resource storage.
         """
         try:
             return self.resource.service.read(entry_id=str(self.service.id), path=path)
@@ -189,9 +186,9 @@ class BaseContext(object):
 
     def get_resource_and_render(self, path=None, variables=None):
         """
-        Read a deployment resource as string from the resource storage and render it as a jinja
-        template using the provided variables. ctx is available to the template without providing it
-        explicitly.
+        Reads a service instance resource as string from the resource storage and renders it as a
+        Jinja template using the provided variables. ``ctx`` is available to the template without
+        providing it explicitly.
         """
         resource_content = self.get_resource(path=path)
         return self._render_resource(resource_content=resource_content, variables=variables)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/exceptions.py b/aria/orchestrator/context/exceptions.py
index fe762e1..e46e2b1 100644
--- a/aria/orchestrator/context/exceptions.py
+++ b/aria/orchestrator/context/exceptions.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-Context based exceptions
+Context exceptions.
 """
+
 from ..exceptions import OrchestratorError
 
 



[14/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index c98a866..883ff4a 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -14,9 +14,7 @@
 # limitations under the License.
 
 """
-classes:
-    * ModelMixin - abstract model implementation.
-    * ModelIDMixin - abstract model implementation with IDs.
+ARIA modeling mix-ins module
 """
 
 from sqlalchemy.ext import associationproxy
@@ -49,11 +47,11 @@ class ModelMixin(object):
 
     def to_dict(self, fields=None, suppress_error=False):
         """
-        Return a dict representation of the model
+        Create a dict representation of the model.
 
-        :param suppress_error: If set to True, sets ``None`` to attributes that it's unable to
-                               retrieve (e.g., if a relationship wasn't established yet, and so it's
-                               impossible to access a property through it)
+        :param suppress_error: if set to ``True``, sets ``None`` to attributes that it's unable to
+         retrieve (e.g., if a relationship wasn't established yet, and so it's impossible to access
+         a property through it)
         """
 
         res = dict()
@@ -79,14 +77,14 @@ class ModelMixin(object):
     @classmethod
     def fields(cls):
         """
-        Return the list of field names for this table
+        List of field names for this table.
 
-        Mostly for backwards compatibility in the code (that uses ``fields``)
+        Mostly for backwards compatibility in the code (that uses ``fields``).
         """
 
         fields = set(cls._iter_association_proxies())
         fields.update(cls.__table__.columns.keys())
-        return fields - set(getattr(cls, '__private_fields__', []))
+        return fields - set(getattr(cls, '__private_fields__', ()))
 
     @classmethod
     def _iter_association_proxies(cls):
@@ -101,8 +99,17 @@ class ModelMixin(object):
 
 
 class ModelIDMixin(object):
-    id = Column(Integer, primary_key=True, autoincrement=True)
-    name = Column(Text, index=True)
+    id = Column(Integer, primary_key=True, autoincrement=True, doc="""
+    Unique ID.
+    
+    :type: :obj:`int`
+    """)
+
+    name = Column(Text, index=True, doc="""
+    Model name.
+    
+    :type: :obj:`basestring`
+    """)
 
     @classmethod
     def id_column_name(cls):
@@ -115,10 +122,10 @@ class ModelIDMixin(object):
 
 class InstanceModelMixin(ModelMixin):
     """
-    Mixin for :class:`ServiceInstance` models.
+    Mix-in for service instance models.
 
-    All models support validation, diagnostic dumping, and representation as
-    raw data (which can be translated into JSON or YAML) via ``as_raw``.
+    All models support validation, diagnostic dumping, and representation as raw data (which can be
+    translated into JSON or YAML) via :meth:`as_raw`.
     """
 
     @property
@@ -137,9 +144,9 @@ class InstanceModelMixin(ModelMixin):
 
 class TemplateModelMixin(InstanceModelMixin):
     """
-    Mixin for :class:`ServiceTemplate` models.
+    Mix-in for service template models.
 
-    All model models can be instantiated into :class:`ServiceInstance` models.
+    All model models can be instantiated into service instance models.
     """
 
     def instantiate(self, container):
@@ -148,24 +155,26 @@ class TemplateModelMixin(InstanceModelMixin):
 
 class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):                                 #pylint: disable=abstract-method
     """
-    Represents a typed value. The value can contain nested intrinsic functions.
+    Mix-in for typed values. The value can contain nested intrinsic functions.
 
-    This model can be used as the ``container_holder`` argument for :func:`functions.evaluate`.
-
-    :ivar name: Name
-    :vartype name: basestring
-    :ivar type_name: Type name
-    :vartype type_name: basestring
-    :ivar value: Value
-    :ivar description: Description
-    :vartype description: basestring
+    This model can be used as the ``container_holder`` argument for
+    :func:`~aria.modeling.functions.evaluate`.
     """
 
     __tablename__ = 'parameter'
 
-    name = Column(Text)
-    type_name = Column(Text)
-    description = Column(Text)
+    type_name = Column(Text, doc="""
+    Type name.
+    
+    :type: :obj:`basestring`
+    """)
+
+    description = Column(Text, doc="""
+    Human-readable description.
+    
+    :type: :obj:`basestring`
+    """)
+
     _value = Column(PickleType)
 
     @property
@@ -187,8 +196,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         """
         The sole owner of this parameter, which is another model that relates to it.
 
-        *All* parameters should have an owner model. In case this property method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
+        *All* parameters should have an owner model.
+
+        :raises ~exceptions.ValueError: if failed to find an owner, which signifies an abnormal,
+         orphaned parameter
         """
 
         # Find first non-null relationship
@@ -210,8 +221,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in
         TOSCA.
 
-        *All* parameters should have a container model. In case this property method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
+        *All* parameters should have a container model.
+
+        :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -253,7 +266,11 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
     @caching.cachedmethod
     def service(self):
         """
-        The :class:`Service` containing this parameter, or None if not contained in a service.
+        The :class:`~aria.modeling.models.Service` model containing this parameter, or ``None`` if
+        not contained in a service.
+
+        :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -268,8 +285,11 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
     @caching.cachedmethod
     def service_template(self):
         """
-        The :class:`ServiceTemplate` containing this parameter, or None if not contained in a
-        service template.
+        The :class:`~aria.modeling.models.ServiceTemplate` model containing this parameter, or
+        ``None`` if not contained in a service template.
+
+        :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -329,10 +349,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
         /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__
 
-        :param name: Parameter name
+        :param name: parameter name
         :type name: basestring
-        :param value: Parameter value
-        :param description: Description (optional)
+        :param value: parameter value
+        :param description: human-readable description (optional)
         :type description: basestring
         """
 
@@ -345,7 +365,6 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
                    description=description)
 
     def as_other_parameter_model(self, other_model_cls):
-
         name, value = self.unwrapped
         return other_model_cls.wrap(name, value)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index f30b86f..cf84fdb 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -13,6 +13,74 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Data models.
+
+Service template models
+-----------------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.modeling.models.ServiceTemplate
+   aria.modeling.models.NodeTemplate
+   aria.modeling.models.GroupTemplate
+   aria.modeling.models.PolicyTemplate
+   aria.modeling.models.SubstitutionTemplate
+   aria.modeling.models.SubstitutionTemplateMapping
+   aria.modeling.models.RequirementTemplate
+   aria.modeling.models.RelationshipTemplate
+   aria.modeling.models.CapabilityTemplate
+   aria.modeling.models.InterfaceTemplate
+   aria.modeling.models.OperationTemplate
+   aria.modeling.models.ArtifactTemplate
+   aria.modeling.models.PluginSpecification
+
+Service instance models
+-----------------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.modeling.models.Service
+   aria.modeling.models.Node
+   aria.modeling.models.Group
+   aria.modeling.models.Policy
+   aria.modeling.models.Substitution
+   aria.modeling.models.SubstitutionMapping
+   aria.modeling.models.Relationship
+   aria.modeling.models.Capability
+   aria.modeling.models.Interface
+   aria.modeling.models.Operation
+   aria.modeling.models.Artifact
+
+Common models
+-------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.modeling.models.Output
+   aria.modeling.models.Input
+   aria.modeling.models.Configuration
+   aria.modeling.models.Property
+   aria.modeling.models.Attribute
+   aria.modeling.models.Type
+   aria.modeling.models.Metadata
+
+Orchestration models
+--------------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.modeling.models.Execution
+   aria.modeling.models.Task
+   aria.modeling.models.Log
+   aria.modeling.models.Plugin
+   aria.modeling.models.Argument
+"""
+
 # pylint: disable=abstract-method
 
 from sqlalchemy.ext.declarative import declarative_base
@@ -28,14 +96,15 @@ from . import (
     service_common,
     orchestration,
     mixins,
+    utils
 )
 
+
 aria_declarative_base = declarative_base(cls=mixins.ModelIDMixin)
 
 
 # See also models_to_register at the bottom of this file
 __all__ = (
-    'aria_declarative_base',
     'models_to_register',
 
     # Service template models
@@ -91,54 +160,68 @@ __all__ = (
 
 # region service template models
 
+@utils.fix_doc
 class ServiceTemplate(aria_declarative_base, service_template.ServiceTemplateBase):
     name = Column(Text, index=True, unique=True)
 
 
+@utils.fix_doc
 class NodeTemplate(aria_declarative_base, service_template.NodeTemplateBase):
     pass
 
 
+@utils.fix_doc
 class GroupTemplate(aria_declarative_base, service_template.GroupTemplateBase):
     pass
 
 
+@utils.fix_doc
 class PolicyTemplate(aria_declarative_base, service_template.PolicyTemplateBase):
     pass
 
 
+@utils.fix_doc
 class SubstitutionTemplate(aria_declarative_base, service_template.SubstitutionTemplateBase):
     pass
 
 
+@utils.fix_doc
 class SubstitutionTemplateMapping(aria_declarative_base,
                                   service_template.SubstitutionTemplateMappingBase):
     pass
 
 
+@utils.fix_doc
 class RequirementTemplate(aria_declarative_base, service_template.RequirementTemplateBase):
     pass
 
 
+@utils.fix_doc
 class RelationshipTemplate(aria_declarative_base, service_template.RelationshipTemplateBase):
     pass
 
 
+@utils.fix_doc
 class CapabilityTemplate(aria_declarative_base, service_template.CapabilityTemplateBase):
     pass
 
 
+@utils.fix_doc
 class InterfaceTemplate(aria_declarative_base, service_template.InterfaceTemplateBase):
     pass
 
 
+@utils.fix_doc
 class OperationTemplate(aria_declarative_base, service_template.OperationTemplateBase):
     pass
 
 
+@utils.fix_doc
 class ArtifactTemplate(aria_declarative_base, service_template.ArtifactTemplateBase):
     pass
 
+
+@utils.fix_doc
 class PluginSpecification(aria_declarative_base, service_template.PluginSpecificationBase):
     pass
 
@@ -147,46 +230,57 @@ class PluginSpecification(aria_declarative_base, service_template.PluginSpecific
 
 # region service instance models
 
+@utils.fix_doc
 class Service(aria_declarative_base, service_instance.ServiceBase):
     name = Column(Text, index=True, unique=True)
 
 
+@utils.fix_doc
 class Node(aria_declarative_base, service_instance.NodeBase):
     pass
 
 
+@utils.fix_doc
 class Group(aria_declarative_base, service_instance.GroupBase):
     pass
 
 
+@utils.fix_doc
 class Policy(aria_declarative_base, service_instance.PolicyBase):
     pass
 
 
+@utils.fix_doc
 class Substitution(aria_declarative_base, service_instance.SubstitutionBase):
     pass
 
 
+@utils.fix_doc
 class SubstitutionMapping(aria_declarative_base, service_instance.SubstitutionMappingBase):
     pass
 
 
+@utils.fix_doc
 class Relationship(aria_declarative_base, service_instance.RelationshipBase):
     pass
 
 
+@utils.fix_doc
 class Capability(aria_declarative_base, service_instance.CapabilityBase):
     pass
 
 
+@utils.fix_doc
 class Interface(aria_declarative_base, service_instance.InterfaceBase):
     pass
 
 
+@utils.fix_doc
 class Operation(aria_declarative_base, service_instance.OperationBase):
     pass
 
 
+@utils.fix_doc
 class Artifact(aria_declarative_base, service_instance.ArtifactBase):
     pass
 
@@ -195,14 +289,17 @@ class Artifact(aria_declarative_base, service_instance.ArtifactBase):
 
 # region service changes models
 
+@utils.fix_doc
 class ServiceUpdate(aria_declarative_base, service_changes.ServiceUpdateBase):
     pass
 
 
+@utils.fix_doc
 class ServiceUpdateStep(aria_declarative_base, service_changes.ServiceUpdateStepBase):
     pass
 
 
+@utils.fix_doc
 class ServiceModification(aria_declarative_base, service_changes.ServiceModificationBase):
     pass
 
@@ -211,31 +308,37 @@ class ServiceModification(aria_declarative_base, service_changes.ServiceModifica
 
 # region common service models
 
-
+@utils.fix_doc
 class Input(aria_declarative_base, service_common.InputBase):
     pass
 
 
+@utils.fix_doc
 class Configuration(aria_declarative_base, service_common.ConfigurationBase):
     pass
 
 
+@utils.fix_doc
 class Output(aria_declarative_base, service_common.OutputBase):
     pass
 
 
+@utils.fix_doc
 class Property(aria_declarative_base, service_common.PropertyBase):
     pass
 
 
+@utils.fix_doc
 class Attribute(aria_declarative_base, service_common.AttributeBase):
     pass
 
 
+@utils.fix_doc
 class Type(aria_declarative_base, service_common.TypeBase):
     pass
 
 
+@utils.fix_doc
 class Metadata(aria_declarative_base, service_common.MetadataBase):
     pass
 
@@ -244,26 +347,30 @@ class Metadata(aria_declarative_base, service_common.MetadataBase):
 
 # region orchestration models
 
+@utils.fix_doc
 class Execution(aria_declarative_base, orchestration.ExecutionBase):
     pass
 
 
+@utils.fix_doc
 class Plugin(aria_declarative_base, orchestration.PluginBase):
     pass
 
 
+@utils.fix_doc
 class Task(aria_declarative_base, orchestration.TaskBase):
     pass
 
 
+@utils.fix_doc
 class Log(aria_declarative_base, orchestration.LogBase):
     pass
 
 
+@utils.fix_doc
 class Argument(aria_declarative_base, orchestration.ArgumentBase):
     pass
 
-
 # endregion
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 829c305..55d4c74 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -14,10 +14,7 @@
 # limitations under the License.
 
 """
-classes:
-    * Execution - execution implementation model.
-    * Plugin - plugin implementation model.
-    * Task - a task
+ARIA modeling orchestration module
 """
 
 # pylint: disable=no-self-argument, no-member, abstract-method
@@ -34,7 +31,6 @@ from sqlalchemy import (
     Float,
     orm,
     PickleType)
-from sqlalchemy.ext.associationproxy import association_proxy
 from sqlalchemy.ext.declarative import declared_attr
 
 from ..orchestrator.exceptions import (TaskAbortException, TaskRetryException)
@@ -47,13 +43,13 @@ from . import (
 
 class ExecutionBase(mixins.ModelMixin):
     """
-    Execution model representation.
+    Workflow execution.
     """
 
     __tablename__ = 'execution'
 
-    __private_fields__ = ['service_fk',
-                          'service_template']
+    __private_fields__ = ('service_fk',
+                          'service_template')
 
     SUCCEEDED = 'succeeded'
     FAILED = 'failed'
@@ -72,50 +68,65 @@ class ExecutionBase(mixins.ModelMixin):
         CANCELLED: PENDING
     }
 
-    @orm.validates('status')
-    def validate_status(self, key, value):
-        """Validation function that verifies execution status transitions are OK"""
-        try:
-            current_status = getattr(self, key)
-        except AttributeError:
-            return
-        valid_transitions = self.VALID_TRANSITIONS.get(current_status, [])
-        if all([current_status is not None,
-                current_status != value,
-                value not in valid_transitions]):
-            raise ValueError('Cannot change execution status from {current} to {new}'.format(
-                current=current_status,
-                new=value))
-        return value
+    # region one_to_many relationships
 
-    created_at = Column(DateTime, index=True)
-    started_at = Column(DateTime, nullable=True, index=True)
-    ended_at = Column(DateTime, nullable=True, index=True)
-    error = Column(Text, nullable=True)
-    status = Column(Enum(*STATES, name='execution_status'), default=PENDING)
-    workflow_name = Column(Text)
+    @declared_attr
+    def inputs(cls):
+        """
+        Execution parameters.
 
-    def has_ended(self):
-        return self.status in self.END_STATES
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
+        return relationship.one_to_many(cls, 'input', dict_key='name')
 
-    def is_active(self):
-        return not self.has_ended() and self.status != self.PENDING
+    @declared_attr
+    def tasks(cls):
+        """
+        Tasks.
+
+        :type: [:class:`Task`]
+        """
+        return relationship.one_to_many(cls, 'task')
 
     @declared_attr
     def logs(cls):
+        """
+        General log messages for the execution (not for its tasks).
+
+        :type: [:class:`Log`]
+        """
         return relationship.one_to_many(cls, 'log')
 
+    # endregion
+
+    # region many_to_one relationships
+
     @declared_attr
     def service(cls):
+        """
+        Associated service.
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service')
 
+    # endregion
+
+    # region association proxies
+
     @declared_attr
-    def tasks(cls):
-        return relationship.one_to_many(cls, 'task')
+    def service_name(cls):
+        return relationship.association_proxy('service', cls.name_column_name())
 
     @declared_attr
-    def inputs(cls):
-        return relationship.one_to_many(cls, 'input', dict_key='name')
+    def service_template(cls):
+        return relationship.association_proxy('service', 'service_template')
+
+    @declared_attr
+    def service_template_name(cls):
+        return relationship.association_proxy('service', 'service_template_name')
+
+    # endregion
 
     # region foreign keys
 
@@ -125,92 +136,70 @@ class ExecutionBase(mixins.ModelMixin):
 
     # endregion
 
-    # region association proxies
+    created_at = Column(DateTime, index=True, doc="""
+    Creation timestamp.
 
-    @declared_attr
-    def service_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', cls.name_column_name())
+    :type: :class:`~datetime.datetime`
+    """)
 
-    @declared_attr
-    def service_template(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', 'service_template')
+    started_at = Column(DateTime, nullable=True, index=True, doc="""
+    Started timestamp.
 
-    @declared_attr
-    def service_template_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', 'service_template_name')
+    :type: :class:`~datetime.datetime`
+    """)
 
-    # endregion
+    ended_at = Column(DateTime, nullable=True, index=True, doc="""
+    Ended timestamp.
 
-    def __str__(self):
-        return '<{0} id=`{1}` (status={2})>'.format(
-            self.__class__.__name__,
-            getattr(self, self.name_column_name()),
-            self.status
-        )
+    :type: :class:`~datetime.datetime`
+    """)
 
+    error = Column(Text, nullable=True, doc="""
+    Error message.
 
-class PluginBase(mixins.ModelMixin):
-    """
-    An installed plugin.
+    :type: :obj:`basestring`
+    """)
 
-    Plugins are usually packaged as `wagons <https://github.com/cloudify-cosmo/wagon>`__, which
-    are archives of one or more `wheels <https://packaging.python.org/distributing/#wheels>`__.
-    Most of these fields are indeed extracted from the installed wagon's metadata.
+    status = Column(Enum(*STATES, name='execution_status'), default=PENDING, doc="""
+    Status.
 
-    :ivar archive_name: Filename (not the full path) of the wagon's archive, often with a ".wgn"
-                        extension
-    :vartype archive_name: basestring
-    :ivar distribution: The name of the operating system on which the wagon was installed (e.g.
-                        "ubuntu")
-    :vartype distribution: basestring
-    :ivar distribution_release: The release of the operating system on which the wagon was installed
-                                (e.g. "trusty")
-    :vartype distribution_release: basestring
-    :ivar distribution_version: The version of the operating system on which the wagon was installed
-                                (e.g. "14.04")
-    :vartype distribution_version: basestring
-    :ivar package_name: The primary Python package name used when the wagon was installed, which is
-                        one of the wheels in the wagon (e.g. "cloudify-script-plugin")
-    :vartype package_name: basestring
-    :ivar package_source: The full install string for the primary Python package name used when the
-                          wagon was installed (e.g. "cloudify-script-plugin==1.2")
-    :vartype package_source: basestring
-    :ivar package_version: The version for the primary Python package name used when the wagon was
-                           installed (e.g. "1.2")
-    :vartype package_version: basestring
-    :ivar supported_platform: If the wheels are *all* pure Python then this would be "any",
-                              otherwise it would be the installed platform name (e.g.
-                              "linux_x86_64")
-    :vartype supported_platform: basestring
-    :ivar supported_py_versions: The Python versions supported by all the wheels (e.g. ["py26",
-                                 "py27"])
-    :vartype supported_py_versions: [basestring]
-    :ivar wheels: The filenames of the wheels archived in the wagon, often with a ".whl" extension
-    :vartype wheels: [basestring]
-    :ivar uploaded_at: Timestamp for when the wagon was installed
-    :vartype uploaded_at: basestring
-    """
+    :type: :obj:`basestring`
+    """)
 
-    __tablename__ = 'plugin'
+    workflow_name = Column(Text, doc="""
+    Workflow name.
 
-    @declared_attr
-    def tasks(cls):
-        return relationship.one_to_many(cls, 'task')
+    :type: :obj:`basestring`
+    """)
+
+    @orm.validates('status')
+    def validate_status(self, key, value):
+        """Validation function that verifies execution status transitions are OK"""
+        try:
+            current_status = getattr(self, key)
+        except AttributeError:
+            return
+        valid_transitions = self.VALID_TRANSITIONS.get(current_status, [])
+        if all([current_status is not None,
+                current_status != value,
+                value not in valid_transitions]):
+            raise ValueError('Cannot change execution status from {current} to {new}'.format(
+                current=current_status,
+                new=value))
+        return value
 
-    archive_name = Column(Text, nullable=False, index=True)
-    distribution = Column(Text)
-    distribution_release = Column(Text)
-    distribution_version = Column(Text)
-    package_name = Column(Text, nullable=False, index=True)
-    package_source = Column(Text)
-    package_version = Column(Text)
-    supported_platform = Column(Text)
-    supported_py_versions = Column(modeling_types.StrictList(basestring))
-    wheels = Column(modeling_types.StrictList(basestring), nullable=False)
-    uploaded_at = Column(DateTime, nullable=False, index=True)
+    def has_ended(self):
+        return self.status in self.END_STATES
+
+    def is_active(self):
+        return not self.has_ended() and self.status != self.PENDING
+
+    def __str__(self):
+        return '<{0} id=`{1}` (status={2})>'.format(
+            self.__class__.__name__,
+            getattr(self, self.name_column_name()),
+            self.status
+        )
 
 
 class TaskBase(mixins.ModelMixin):
@@ -219,46 +208,20 @@ class TaskBase(mixins.ModelMixin):
     outputs, as well as an atomic status, ensuring that the task can only be running once at any
     given time.
 
+    The Python :attr:`function` is usually provided by an associated :class:`Plugin`. The
+    :attr:`arguments` of the function should be set according to the specific signature of the
+    function.
+
     Tasks may be "one shot" or may be configured to run repeatedly in the case of failure.
 
     Tasks are often based on :class:`Operation`, and thus act on either a :class:`Node` or a
     :class:`Relationship`, however this is not required.
-
-    :ivar node: The node actor (optional)
-    :vartype node: :class:`Node`
-    :ivar relationship: The relationship actor (optional)
-    :vartype relationship: :class:`Relationship`
-    :ivar plugin: The implementing plugin (set to None for default execution plugin)
-    :vartype plugin: :class:`Plugin`
-    :ivar function: Python path to an ``@operation`` function
-    :vartype function: basestring
-    :ivar arguments: Arguments that can be used by this task
-    :vartype arguments: {basestring: :class:`Argument`}
-    :ivar max_attempts: Maximum number of retries allowed in case of failure
-    :vartype max_attempts: int
-    :ivar retry_interval: Interval between retries (in seconds)
-    :vartype retry_interval: int
-    :ivar ignore_failure: Set to True to ignore failures
-    :vartype ignore_failure: bool
-    :ivar due_at: Timestamp to start the task
-    :vartype due_at: datetime
-    :ivar execution: Assigned execution
-    :vartype execution: :class:`Execution`
-    :ivar status: Current atomic status ('pending', 'retrying', 'sent', 'started', 'success',
-                  'failed')
-    :vartype status: basestring
-    :ivar started_at: Timestamp for when task started
-    :vartype started_at: datetime
-    :ivar ended_at: Timestamp for when task ended
-    :vartype ended_at: datetime
-    :ivar attempts_count: How many attempts occurred
-    :vartype attempts_count: int
     """
 
     __tablename__ = 'task'
 
-    __private_fields__ = ['dependency_operation_task_fk', 'dependency_stub_task_fk', 'node_fk',
-                          'relationship_fk', 'plugin_fk', 'execution_fk']
+    __private_fields__ = ('dependency_operation_task_fk', 'dependency_stub_task_fk', 'node_fk',
+                          'relationship_fk', 'plugin_fk', 'execution_fk')
 
     START_WORKFLOW = 'start_workflow'
     END_WORKFLOW = 'end_workflow'
@@ -292,70 +255,91 @@ class TaskBase(mixins.ModelMixin):
     )
     INFINITE_RETRIES = -1
 
+    # region one_to_many relationships
+
     @declared_attr
-    def execution(cls):
-        return relationship.many_to_one(cls, 'execution')
+    def logs(cls):
+        """
+        Log messages.
+
+        :type: [:class:`Log`]
+        """
+        return relationship.one_to_many(cls, 'log')
 
     @declared_attr
-    def execution_fk(cls):
-        return relationship.foreign_key('execution', nullable=True)
+    def arguments(cls):
+        """
+        Arguments sent to the Python :attr:`function``.
 
-    status = Column(Enum(*STATES, name='status'), default=PENDING)
-    due_at = Column(DateTime, nullable=False, index=True, default=datetime.utcnow())
-    started_at = Column(DateTime, default=None)
-    ended_at = Column(DateTime, default=None)
-    attempts_count = Column(Integer, default=1)
+        :type: {:obj:`basestring`: :class:`Argument`}
+        """
+        return relationship.one_to_many(cls, 'argument', dict_key='name')
 
-    _executor = Column(PickleType)
-    _context_cls = Column(PickleType)
-    _stub_type = Column(Enum(*STUB_TYPES))
+    # endregion
+
+    # region many_one relationships
 
     @declared_attr
-    def logs(cls):
-        return relationship.one_to_many(cls, 'log')
+    def execution(cls):
+        """
+        Containing execution.
+
+        :type: :class:`Execution`
+        """
+        return relationship.many_to_one(cls, 'execution')
 
     @declared_attr
     def node(cls):
+        """
+        Node actor (can be ``None``).
+
+        :type: :class:`Node`
+        """
         return relationship.many_to_one(cls, 'node')
 
     @declared_attr
     def relationship(cls):
+        """
+        Relationship actor (can be ``None``).
+
+        :type: :class:`Relationship`
+        """
         return relationship.many_to_one(cls, 'relationship')
 
     @declared_attr
     def plugin(cls):
+        """
+        Associated plugin.
+
+        :type: :class:`Plugin`
+        """
         return relationship.many_to_one(cls, 'plugin')
 
+    # endregion
+
+    # region association proxies
+
     @declared_attr
-    def arguments(cls):
-        return relationship.one_to_many(cls, 'argument', dict_key='name')
+    def node_name(cls):
+        return relationship.association_proxy('node', cls.name_column_name())
 
-    function = Column(String)
-    max_attempts = Column(Integer, default=1)
-    retry_interval = Column(Float, default=0)
-    ignore_failure = Column(Boolean, default=False)
-    interface_name = Column(String)
-    operation_name = Column(String)
+    @declared_attr
+    def relationship_name(cls):
+        return relationship.association_proxy('relationship', cls.name_column_name())
 
-    @property
-    def actor(self):
-        """
-        Return the actor of the task
-        :return:
-        """
-        return self.node or self.relationship
+    @declared_attr
+    def execution_name(cls):
+        return relationship.association_proxy('execution', cls.name_column_name())
 
-    @orm.validates('max_attempts')
-    def validate_max_attempts(self, _, value):                                  # pylint: disable=no-self-use
-        """Validates that max attempts is either -1 or a positive number"""
-        if value < 1 and value != TaskBase.INFINITE_RETRIES:
-            raise ValueError('Max attempts can be either -1 (infinite) or any positive number. '
-                             'Got {value}'.format(value=value))
-        return value
+    # endregion
 
     # region foreign keys
 
     @declared_attr
+    def execution_fk(cls):
+        return relationship.foreign_key('execution', nullable=True)
+
+    @declared_attr
     def node_fk(cls):
         return relationship.foreign_key('node', nullable=True)
 
@@ -369,24 +353,93 @@ class TaskBase(mixins.ModelMixin):
 
     # endregion
 
-    # region association proxies
+    status = Column(Enum(*STATES, name='status'), default=PENDING, doc="""
+    Current atomic status ('pending', 'retrying', 'sent', 'started', 'success', 'failed').
 
-    @declared_attr
-    def node_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('node', cls.name_column_name())
+    :type: :obj:`basestring`
+    """)
 
-    @declared_attr
-    def relationship_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('relationship', cls.name_column_name())
+    due_at = Column(DateTime, nullable=False, index=True, default=datetime.utcnow(), doc="""
+    Timestamp to start the task.
 
-    @declared_attr
-    def execution_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('execution', cls.name_column_name())
+    :type: :class:`~datetime.datetime`
+    """)
 
-    # endregion
+    started_at = Column(DateTime, default=None, doc="""
+    Started timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    ended_at = Column(DateTime, default=None, doc="""
+    Ended timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    attempts_count = Column(Integer, default=1, doc="""
+    How many attempts occurred.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    function = Column(String, doc="""
+    Full path to Python function.
+
+    :type: :obj:`basestring`
+    """)
+
+    max_attempts = Column(Integer, default=1, doc="""
+    Maximum number of attempts allowed in case of task failure.
+
+    :type: :obj:`int`
+    """)
+
+    retry_interval = Column(Float, default=0, doc="""
+    Interval between task retry attemps (in seconds).
+
+    :type: :obj:`float`
+    """)
+
+    ignore_failure = Column(Boolean, default=False, doc="""
+    Set to ``True`` to ignore failures.
+
+    :type: :obj:`bool`
+    """)
+
+    interface_name = Column(String, doc="""
+    Name of interface on node or relationship.
+
+    :type: :obj:`basestring`
+    """)
+
+    operation_name = Column(String, doc="""
+    Name of operation in interface on node or relationship.
+
+    :type: :obj:`basestring`
+    """)
+
+    _api_id = Column(String)
+    _executor = Column(PickleType)
+    _context_cls = Column(PickleType)
+    _stub_type = Column(Enum(*STUB_TYPES))
+
+    @property
+    def actor(self):
+        """
+        Actor of the task (node or relationship).
+        """
+        return self.node or self.relationship
+
+    @orm.validates('max_attempts')
+    def validate_max_attempts(self, _, value):                                  # pylint: disable=no-self-use
+        """
+        Validates that max attempts is either -1 or a positive number.
+        """
+        if value < 1 and value != TaskBase.INFINITE_RETRIES:
+            raise ValueError('Max attempts can be either -1 (infinite) or any positive number. '
+                             'Got {value}'.format(value=value))
+        return value
 
     @staticmethod
     def abort(message=None):
@@ -447,26 +500,36 @@ class TaskBase(mixins.ModelMixin):
 
 
 class LogBase(mixins.ModelMixin):
+    """
+    Single log message.
+    """
 
     __tablename__ = 'log'
 
-    __private_fields__ = ['execution_fk',
-                          'task_fk']
+    __private_fields__ = ('execution_fk',
+                          'task_fk')
+
+    # region many_to_one relationships
 
     @declared_attr
     def execution(cls):
+        """
+        Containing execution.
+
+        :type: :class:`Execution`
+        """
         return relationship.many_to_one(cls, 'execution')
 
     @declared_attr
     def task(cls):
-        return relationship.many_to_one(cls, 'task')
+        """
+        Containing task (can be ``None``).
 
-    level = Column(String)
-    msg = Column(String)
-    created_at = Column(DateTime, index=True)
+        :type: :class:`Task`
+        """
+        return relationship.many_to_one(cls, 'task')
 
-    # In case of failed execution
-    traceback = Column(Text)
+    # endregion
 
     # region foreign keys
 
@@ -480,6 +543,30 @@ class LogBase(mixins.ModelMixin):
 
     # endregion
 
+    level = Column(String, doc="""
+    Log level.
+
+    :type: :obj:`basestring`
+    """)
+
+    msg = Column(String, doc="""
+    Log message.
+
+    :type: :obj:`basestring`
+    """)
+
+    created_at = Column(DateTime, index=True, doc="""
+    Creation timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+    traceback = Column(Text, doc="""
+    Error traceback in case of failure.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
     def __str__(self):
         return self.msg
 
@@ -488,30 +575,137 @@ class LogBase(mixins.ModelMixin):
         return '{name}: {self.msg}'.format(name=name, self=self)
 
 
-class ArgumentBase(mixins.ParameterMixin):
+class PluginBase(mixins.ModelMixin):
+    """
+    Installed plugin.
 
-    __tablename__ = 'argument'
+    Plugins are usually packaged as `wagons <https://github.com/cloudify-cosmo/wagon>`__, which
+    are archives of one or more `wheels <https://packaging.python.org/distributing/#wheels>`__.
+    Most of these fields are indeed extracted from the installed wagon's metadata.
+    """
 
-    # region foreign keys
+    __tablename__ = 'plugin'
 
-    @declared_attr
-    def task_fk(cls):
-        return relationship.foreign_key('task', nullable=True)
+    # region one_to_many relationships
 
     @declared_attr
-    def operation_fk(cls):
-        return relationship.foreign_key('operation', nullable=True)
+    def tasks(cls):
+        """
+        Associated Tasks.
+
+        :type: [:class:`Task`]
+        """
+        return relationship.one_to_many(cls, 'task')
 
     # endregion
 
+    archive_name = Column(Text, nullable=False, index=True, doc="""
+    Filename (not the full path) of the wagon's archive, often with a ``.wgn`` extension.
+
+    :type: :obj:`basestring`
+    """)
+
+    distribution = Column(Text, doc="""
+    Name of the operating system on which the wagon was installed (e.g. ``ubuntu``).
+
+    :type: :obj:`basestring`
+    """)
+
+    distribution_release = Column(Text, doc="""
+    Release of the operating system on which the wagon was installed (e.g. ``trusty``).
+
+    :type: :obj:`basestring`
+    """)
+
+    distribution_version = Column(Text, doc="""
+    Version of the operating system on which the wagon was installed (e.g. ``14.04``).
+
+    :type: :obj:`basestring`
+    """)
+
+    package_name = Column(Text, nullable=False, index=True, doc="""
+    Primary Python package name used when the wagon was installed, which is one of the wheels in the
+    wagon (e.g. ``cloudify-script-plugin``).
+
+    :type: :obj:`basestring`
+    """)
+
+    package_source = Column(Text, doc="""
+    Full install string for the primary Python package name used when the wagon was installed (e.g.
+    ``cloudify-script-plugin==1.2``).
+
+    :type: :obj:`basestring`
+    """)
+
+    package_version = Column(Text, doc="""
+    Version for the primary Python package name used when the wagon was installed (e.g. ``1.2``).
+
+    :type: :obj:`basestring`
+    """)
+
+    supported_platform = Column(Text, doc="""
+    If the wheels are *all* pure Python then this would be "any", otherwise it would be the
+    installed platform name (e.g. ``linux_x86_64``).
+
+    :type: :obj:`basestring`
+    """)
+
+    supported_py_versions = Column(modeling_types.StrictList(basestring), doc="""
+    Python versions supported by all the wheels (e.g. ``["py26", "py27"]``)
+
+    :type: [:obj:`basestring`]
+    """)
+
+    wheels = Column(modeling_types.StrictList(basestring), nullable=False, doc="""
+    Filenames of the wheels archived in the wagon, often with a ``.whl`` extension.
+
+    :type: [:obj:`basestring`]
+    """)
+
+    uploaded_at = Column(DateTime, nullable=False, index=True, doc="""
+    Timestamp for when the wagon was installed.
+
+    :type: :class:`~datetime.datetime`
+    """)
+
+
+class ArgumentBase(mixins.ParameterMixin):
+    """
+    Python function argument parameter.
+    """
+
+    __tablename__ = 'argument'
+
     # region many_to_one relationships
 
     @declared_attr
     def task(cls):
+        """
+        Containing task (can be ``None``);
+
+        :type: :class:`Task`
+        """
         return relationship.many_to_one(cls, 'task')
 
     @declared_attr
     def operation(cls):
+        """
+        Containing operation (can be ``None``);
+
+        :type: :class:`Operation`
+        """
         return relationship.many_to_one(cls, 'operation')
 
     # endregion
+
+    # region foreign keys
+
+    @declared_attr
+    def task_fk(cls):
+        return relationship.foreign_key('task', nullable=True)
+
+    @declared_attr
+    def operation_fk(cls):
+        return relationship.foreign_key('operation', nullable=True)
+
+    # endregion

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index 76ac316..51fbfd6 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -13,9 +13,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+ARIA modeling relationship module
+"""
+
 # pylint: disable=invalid-name, redefined-outer-name
+
 from sqlalchemy.orm import relationship, backref
 from sqlalchemy.orm.collections import attribute_mapped_collection
+from sqlalchemy.ext.associationproxy import association_proxy as original_association_proxy
 from sqlalchemy import (
     Column,
     ForeignKey,
@@ -43,9 +49,9 @@ def foreign_key(other_table, nullable=False):
 
     *This utility method should only be used during class creation.*
 
-    :param other_table: Other table name
+    :param other_table: other table name
     :type other_table: basestring
-    :param nullable: True to allow null values (meaning that there is no relationship)
+    :param nullable: ``True`` to allow null values (meaning that there is no relationship)
     :type nullable: bool
     """
 
@@ -63,9 +69,9 @@ def one_to_one_self(model_class, fk):
 
     *This utility method should only be used during class creation.*
 
-    :param model_class: The class in which this relationship will be declared
+    :param model_class: class in which this relationship will be declared
     :type model_class: type
-    :param fk: Foreign key name
+    :param fk: foreign key name
     :type fk: basestring
     """
 
@@ -90,6 +96,35 @@ def one_to_one_self(model_class, fk):
     )
 
 
+def one_to_many_self(model_class, fk, dict_key=None):
+    """
+    Declare a one-to-many relationship property. The property value would be a list or dict of
+    instances of the same model.
+
+    You will need an associated foreign key to our own table.
+
+    *This utility method should only be used during class creation.*
+
+    :param model_class: class in which this relationship will be declared
+    :type model_class: type
+    :param fk: Foreign key name
+    :type fk: basestring
+    :param dict_key: if set the value will be a dict with this key as the dict key; otherwise will
+     be a list
+    :type dict_key: basestring
+    """
+    return _relationship(
+        model_class,
+        model_class.__tablename__,
+        relationship_kwargs={
+            'remote_side': '{model_class}.{remote_column}'.format(
+                model_class=model_class.__name__, remote_column=fk)
+        },
+        back_populates=False,
+        dict_key=dict_key
+    )
+
+
 def one_to_one(model_class,
                other_table,
                fk=None,
@@ -105,17 +140,17 @@ def one_to_one(model_class,
 
     *This utility method should only be used during class creation.*
 
-    :param model_class: The class in which this relationship will be declared
+    :param model_class: class in which this relationship will be declared
     :type model_class: type
-    :param other_table: Other table name
+    :param other_table: other table name
     :type other_table: basestring
-    :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
+    :param fk: foreign key name at our table (no need specify if there's no ambiguity)
     :type fk: basestring
-    :param other_fk: Foreign key name at the other table (no need specify if there's no ambiguity)
+    :param other_fk: foreign key name at the other table (no need specify if there's no ambiguity)
     :type other_fk: basestring
-    :param back_populates: Override name of matching many-to-many property at other table; set to
-                       false to disable
-    :type back_populates: basestring|bool
+    :param back_populates: override name of matching many-to-many property at other table; set to
+     ``False`` to disable
+    :type back_populates: basestring or bool
     """
     backref_kwargs = None
     if back_populates is not NO_BACK_POP:
@@ -150,18 +185,18 @@ def one_to_many(model_class,
 
     *This utility method should only be used during class creation.*
 
-    :param model_class: The class in which this relationship will be declared
+    :param model_class: class in which this relationship will be declared
     :type model_class: type
-    :param child_table: Child table name
+    :param other_table: other table name
     :type other_table: basestring
-    :param other_fk: Foreign key name at the child table (no need specify if there's no ambiguity)
+    :param other_fk: foreign key name at the other table (no need specify if there's no ambiguity)
     :type other_fk: basestring
-    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
-                     be a list
+    :param dict_key: if set the value will be a dict with this key as the dict key; otherwise will
+     be a list
     :type dict_key: basestring
-    :param back_populates: Override name of matching many-to-one property at child table; set to
-                           false to disable
-    :type back_populates: basestring|bool
+    :param back_populates: override name of matching many-to-one property at other table; set to
+     ``false`` to disable
+    :type back_populates: basestring or bool
     """
     relationship_kwargs = rel_kwargs or {}
     if self:
@@ -201,19 +236,19 @@ def many_to_one(model_class,
     The declaration will automatically create a matching one-to-many property at the child model,
     named after the plural form of our table name. Use the ``parent_property`` argument to override
     this name. Note: the automatic property will always be a SQLAlchemy query object; if you need a
-    Python collection then use :meth:`one_to_many` at that model.
+    Python collection then use :func:`one_to_many` at that model.
 
     *This utility method should only be used during class creation.*
 
-    :param model_class: The class in which this relationship will be declared
+    :param model_class: class in which this relationship will be declared
     :type model_class: type
-    :param parent_table: Parent table name
+    :param parent_table: parent table name
     :type parent_table: basestring
-    :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
+    :param fk: foreign key name at our table (no need specify if there's no ambiguity)
     :type fk: basestring
-    :param back_populates: Override name of matching one-to-many property at parent table; set to
-                            false to disable
-    :type back_populates: basestring|bool
+    :param back_populates: override name of matching one-to-many property at parent table; set to
+     ``False`` to disable
+    :type back_populates: basestring or bool
     """
     if back_populates is None:
         back_populates = formatting.pluralize(model_class.__tablename__)
@@ -241,22 +276,22 @@ def many_to_many(model_class,
     The declaration will automatically create a matching many-to-many property at the other model,
     named after the plural form of our table name. Use the ``other_property`` argument to override
     this name. Note: the automatic property will always be a SQLAlchemy query object; if you need a
-    Python collection then use :meth:`many_to_many` again at that model.
+    Python collection then use :func:`many_to_many` again at that model.
 
     *This utility method should only be used during class creation.*
 
-    :param model_class: The class in which this relationship will be declared
+    :param model_class: class in which this relationship will be declared
     :type model_class: type
-    :param other_table: Parent table name
+    :param other_table: parent table name
     :type other_table: basestring
-    :param prefix: Optional prefix for extra table name as well as for ``other_property``
+    :param prefix: optional prefix for extra table name as well as for ``other_property``
     :type prefix: basestring
-    :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
-                     be a list
+    :param dict_key: if set the value will be a dict with this key as the dict key; otherwise will
+     be a list
     :type dict_key: basestring
-    :param other_property: Override name of matching many-to-many property at other table; set to
-                           false to disable
-    :type other_property: basestring|bool
+    :param other_property: override name of matching many-to-many property at other table; set to
+     ``False`` to disable
+    :type other_property: basestring or bool
     """
 
     this_table = model_class.__tablename__
@@ -301,6 +336,21 @@ def many_to_many(model_class,
     return _relationship(model_class, other_table, **kwargs)
 
 
+def association_proxy(*args, **kwargs):
+    if 'type' in kwargs:
+        type_ = kwargs.get('type')
+        del kwargs['type']
+    else:
+        type_ = ':obj:`basestring`'
+    proxy = original_association_proxy(*args, **kwargs)
+    proxy.__doc__ = """
+    Internal. For use in SQLAlchemy queries.
+
+    :type: {0}
+    """.format(type_)
+    return proxy
+
+
 def _relationship(model_class,
                   other_table_name,
                   back_populates=None,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/service_changes.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_changes.py b/aria/modeling/service_changes.py
index f632fef..061262a 100644
--- a/aria/modeling/service_changes.py
+++ b/aria/modeling/service_changes.py
@@ -14,10 +14,7 @@
 # limitations under the License.
 
 """
-classes:
-    * ServiceUpdate - service update implementation model.
-    * ServiceUpdateStep - service update step implementation model.
-    * ServiceModification - service modification implementation model.
+ARIA modeling service changes module
 """
 
 # pylint: disable=no-self-argument, no-member, abstract-method
@@ -30,7 +27,6 @@ from sqlalchemy import (
     DateTime,
     Enum,
 )
-from sqlalchemy.ext.associationproxy import association_proxy
 from sqlalchemy.ext.declarative import declared_attr
 
 from .types import (List, Dict)
@@ -44,8 +40,8 @@ class ServiceUpdateBase(ModelMixin):
     """
     __tablename__ = 'service_update'
 
-    __private_fields__ = ['service_fk',
-                          'execution_fk']
+    __private_fields__ = ('service_fk',
+                          'execution_fk')
 
     created_at = Column(DateTime, nullable=False, index=True)
     service_plan = Column(Dict, nullable=False)
@@ -55,29 +51,15 @@ class ServiceUpdateBase(ModelMixin):
     modified_entity_ids = Column(Dict)
     state = Column(Text)
 
-    # region foreign keys
-
-    @declared_attr
-    def execution_fk(cls):
-        return relationship.foreign_key('execution', nullable=True)
-
-    @declared_attr
-    def service_fk(cls):
-        return relationship.foreign_key('service')
-
-    # endregion
-
     # region association proxies
 
     @declared_attr
     def execution_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('execution', cls.name_column_name())
+        return relationship.association_proxy('execution', cls.name_column_name())
 
     @declared_attr
     def service_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', cls.name_column_name())
+        return relationship.association_proxy('service', cls.name_column_name())
 
     # endregion
 
@@ -105,6 +87,18 @@ class ServiceUpdateBase(ModelMixin):
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def execution_fk(cls):
+        return relationship.foreign_key('execution', nullable=True)
+
+    @declared_attr
+    def service_fk(cls):
+        return relationship.foreign_key('service')
+
+    # endregion
+
     def to_dict(self, suppress_error=False, **kwargs):
         dep_update_dict = super(ServiceUpdateBase, self).to_dict(suppress_error)     #pylint: disable=no-member
         # Taking care of the fact the DeploymentSteps are _BaseModels
@@ -119,7 +113,7 @@ class ServiceUpdateStepBase(ModelMixin):
 
     __tablename__ = 'service_update_step'
 
-    __private_fields__ = ['service_update_fk']
+    __private_fields__ = ('service_update_fk',)
 
     _action_types = namedtuple('ACTION_TYPES', 'ADD, REMOVE, MODIFY')
     ACTION_TYPES = _action_types(ADD='add', REMOVE='remove', MODIFY='modify')
@@ -143,20 +137,11 @@ class ServiceUpdateStepBase(ModelMixin):
     entity_id = Column(Text, nullable=False)
     entity_type = Column(Enum(*ENTITY_TYPES, name='entity_type'), nullable=False)
 
-    # region foreign keys
-
-    @declared_attr
-    def service_update_fk(cls):
-        return relationship.foreign_key('service_update')
-
-    # endregion
-
     # region association proxies
 
     @declared_attr
     def service_update_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service_update', cls.name_column_name())
+        return relationship.association_proxy('service_update', cls.name_column_name())
 
     # endregion
 
@@ -176,6 +161,14 @@ class ServiceUpdateStepBase(ModelMixin):
 
     # endregion
 
+    # region foreign keys
+
+    @declared_attr
+    def service_update_fk(cls):
+        return relationship.foreign_key('service_update')
+
+    # endregion
+
     def __hash__(self):
         return hash((getattr(self, self.id_column_name()), self.entity_id))
 
@@ -211,7 +204,7 @@ class ServiceModificationBase(ModelMixin):
 
     __tablename__ = 'service_modification'
 
-    __private_fields__ = ['service_fk']
+    __private_fields__ = ('service_fk',)
 
     STARTED = 'started'
     FINISHED = 'finished'
@@ -227,20 +220,11 @@ class ServiceModificationBase(ModelMixin):
     nodes = Column(Dict)
     status = Column(Enum(*STATES, name='service_modification_status'))
 
-    # region foreign keys
-
-    @declared_attr
-    def service_fk(cls):
-        return relationship.foreign_key('service')
-
-    # endregion
-
     # region association proxies
 
     @declared_attr
     def service_name(cls):
-        """Required for use by SQLAlchemy queries"""
-        return association_proxy('service', cls.name_column_name())
+        return relationship.association_proxy('service', cls.name_column_name())
 
     # endregion
 
@@ -253,8 +237,17 @@ class ServiceModificationBase(ModelMixin):
     # endregion
 
     # region many_to_one relationships
+
     @declared_attr
     def service(cls):
         return relationship.many_to_one(cls, 'service', back_populates='modifications')
 
     # endregion
+
+    # region foreign keys
+
+    @declared_attr
+    def service_fk(cls):
+        return relationship.foreign_key('service')
+
+    # endregion

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 0bb861f..b533a88 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+ARIA modeling service common module
+"""
+
 # pylint: disable=no-self-argument, no-member, abstract-method
 
 from sqlalchemy import (
@@ -32,9 +36,34 @@ from . import relationship
 
 
 class OutputBase(ParameterMixin):
+    """
+    Output parameter or declaration for an output parameter.
+    """
 
     __tablename__ = 'output'
 
+    # region many_to_one relationships
+
+    @declared_attr
+    def service_template(cls):
+        """
+        Containing service template (can be ``None``).
+
+        :type: :class:`ServiceTemplate`
+        """
+        return relationship.many_to_one(cls, 'service_template')
+
+    @declared_attr
+    def service(cls):
+        """
+        Containing service (can be ``None``).
+
+        :type: :class:`ServiceTemplate`
+        """
+        return relationship.many_to_one(cls, 'service')
+
+    # endregion
+
     # region foreign keys
 
     @declared_attr
@@ -47,22 +76,80 @@ class OutputBase(ParameterMixin):
 
     # endregion
 
+
+class InputBase(ParameterMixin):
+    """
+    Input parameter or declaration for an input parameter.
+    """
+
+    __tablename__ = 'input'
+
     # region many_to_one relationships
 
     @declared_attr
     def service_template(cls):
+        """
+        Containing service template (can be ``None``).
+
+        :type: :class:`ServiceTemplate`
+        """
         return relationship.many_to_one(cls, 'service_template')
 
     @declared_attr
     def service(cls):
+        """
+        Containing service (can be ``None``).
+
+        :type: :class:`Service`
+        """
         return relationship.many_to_one(cls, 'service')
 
-    # endregion
+    @declared_attr
+    def interface(cls):
+        """
+        Containing interface (can be ``None``).
 
+        :type: :class:`Interface`
+        """
+        return relationship.many_to_one(cls, 'interface')
 
-class InputBase(ParameterMixin):
+    @declared_attr
+    def operation(cls):
+        """
+        Containing operation (can be ``None``).
 
-    __tablename__ = 'input'
+        :type: :class:`Operation`
+        """
+        return relationship.many_to_one(cls, 'operation')
+
+    @declared_attr
+    def interface_template(cls):
+        """
+        Containing interface template (can be ``None``).
+
+        :type: :class:`InterfaceTemplate`
+        """
+        return relationship.many_to_one(cls, 'interface_template')
+
+    @declared_attr
+    def operation_template(cls):
+        """
+        Containing operation template (can be ``None``).
+
+        :type: :class:`OperationTemplate`
+        """
+        return relationship.many_to_one(cls, 'operation_template')
+
+    @declared_attr
+    def execution(cls):
+        """
+        Containing execution (can be ``None``).
+
+        :type: :class:`Execution`
+        """
+        return relationship.many_to_one(cls, 'execution')
+
+    # endregion
 
     # region foreign keys
 
@@ -100,71 +187,167 @@ class InputBase(ParameterMixin):
 
     # endregion
 
+
+class ConfigurationBase(ParameterMixin):
+    """
+    Configuration parameter.
+    """
+
+    __tablename__ = 'configuration'
+
     # region many_to_one relationships
 
     @declared_attr
-    def service_template(cls):
-        return relationship.many_to_one(cls, 'service_template')
+    def operation_template(cls):
+        """
+        Containing operation template (can be ``None``).
+
+        :type: :class:`OperationTemplate`
+        """
+        return relationship.many_to_one(cls, 'operation_template')
 
     @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service')
+    def operation(cls):
+        """
+        Containing operation (can be ``None``).
+
+        :type: :class:`Operation`
+        """
+        return relationship.many_to_one(cls, 'operation')
+
+    # endregion
+
+    # region foreign keys
 
     @declared_attr
-    def interface(cls):
-        return relationship.many_to_one(cls, 'interface')
+    def operation_template_fk(cls):
+        return relationship.foreign_key('operation_template', nullable=True)
 
     @declared_attr
-    def operation(cls):
-        return relationship.many_to_one(cls, 'operation')
+    def operation_fk(cls):
+        return relationship.foreign_key('operation', nullable=True)
+
+    # endregion
+
+
+class PropertyBase(ParameterMixin):
+    """
+    Property parameter or declaration for a property parameter.
+    """
+
+    __tablename__ = 'property'
+
+    # region many_to_one relationships
 
     @declared_attr
-    def interface_template(cls):
-        return relationship.many_to_one(cls, 'interface_template')
+    def node_template(cls):
+        """
+        Containing node template (can be ``None``).
+
+        :type: :class:`NodeTemplate`
+        """
+        return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_template')
+    def group_template(cls):
+        """
+        Containing group template (can be ``None``).
+
+        :type: :class:`GroupTemplate`
+        """
+        return relationship.many_to_one(cls, 'group_template')
 
     @declared_attr
-    def execution(cls):
-        return relationship.many_to_one(cls, 'execution')
+    def policy_template(cls):
+        """
+        Containing policy template (can be ``None``).
 
-    # endregion
+        :type: :class:`PolicyTemplate`
+        """
+        return relationship.many_to_one(cls, 'policy_template')
 
+    @declared_attr
+    def relationship_template(cls):
+        """
+        Containing relationship template (can be ``None``).
 
-class ConfigurationBase(ParameterMixin):
+        :type: :class:`RelationshipTemplate`
+        """
+        return relationship.many_to_one(cls, 'relationship_template')
 
-    __tablename__ = 'configuration'
+    @declared_attr
+    def capability_template(cls):
+        """
+        Containing capability template (can be ``None``).
 
-    # region foreign keys
+        :type: :class:`CapabilityTemplate`
+        """
+        return relationship.many_to_one(cls, 'capability_template')
 
     @declared_attr
-    def operation_template_fk(cls):
-        return relationship.foreign_key('operation_template', nullable=True)
+    def artifact_template(cls):
+        """
+        Containing artifact template (can be ``None``).
+
+        :type: :class:`ArtifactTemplate`
+        """
+        return relationship.many_to_one(cls, 'artifact_template')
 
     @declared_attr
-    def operation_fk(cls):
-        return relationship.foreign_key('operation', nullable=True)
+    def node(cls):
+        """
+        Containing node (can be ``None``).
 
-    # endregion
+        :type: :class:`Node`
+        """
+        return relationship.many_to_one(cls, 'node')
 
-    # region many_to_one relationships
+    @declared_attr
+    def group(cls):
+        """
+        Containing group (can be ``None``).
+
+        :type: :class:`Group`
+        """
+        return relationship.many_to_one(cls, 'group')
 
     @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_template')
+    def policy(cls):
+        """
+        Containing policy (can be ``None``).
+
+        :type: :class:`Policy`
+        """
+        return relationship.many_to_one(cls, 'policy')
 
     @declared_attr
-    def operation(cls):
-        return relationship.many_to_one(cls, 'operation')
+    def relationship(cls):
+        """
+        Containing relationship (can be ``None``).
 
-    # endregion
+        :type: :class:`Relationship`
+        """
+        return relationship.many_to_one(cls, 'relationship')
 
+    @declared_attr
+    def capability(cls):
+        """
+        Containing capability (can be ``None``).
 
-class PropertyBase(ParameterMixin):
+        :type: :class:`Capability`
+        """
+        return relationship.many_to_one(cls, 'capability')
 
-    __tablename__ = 'property'
+    @declared_attr
+    def artifact(cls):
+        """
+        Containing artifact (can be ``None``).
+
+        :type: :class:`Artifact`
+        """
+        return relationship.many_to_one(cls, 'artifact')
+
+    # endregion
 
     # region foreign keys
 
@@ -215,65 +398,39 @@ class PropertyBase(ParameterMixin):
     @declared_attr
     def artifact_fk(cls):
         return relationship.foreign_key('artifact', nullable=True)
+
     # endregion
 
-    # region many_to_one relationships
 
-    @declared_attr
-    def node_template(cls):
-        return relationship.many_to_one(cls, 'node_template')
-
-    @declared_attr
-    def group_template(cls):
-        return relationship.many_to_one(cls, 'group_template')
+class AttributeBase(ParameterMixin):
+    """
+    Attribute parameter or declaration for an attribute parameter.
+    """
 
-    @declared_attr
-    def policy_template(cls):
-        return relationship.many_to_one(cls, 'policy_template')
+    __tablename__ = 'attribute'
 
-    @declared_attr
-    def relationship_template(cls):
-        return relationship.many_to_one(cls, 'relationship_template')
+    # region many_to_one relationships
 
     @declared_attr
-    def capability_template(cls):
-        return relationship.many_to_one(cls, 'capability_template')
+    def node_template(cls):
+        """
+        Containing node template (can be ``None``).
 
-    @declared_attr
-    def artifact_template(cls):
-        return relationship.many_to_one(cls, 'artifact_template')
+        :type: :class:`NodeTemplate`
+        """
+        return relationship.many_to_one(cls, 'node_template')
 
     @declared_attr
     def node(cls):
-        return relationship.many_to_one(cls, 'node')
-
-    @declared_attr
-    def group(cls):
-        return relationship.many_to_one(cls, 'group')
-
-    @declared_attr
-    def policy(cls):
-        return relationship.many_to_one(cls, 'policy')
-
-    @declared_attr
-    def relationship(cls):
-        return relationship.many_to_one(cls, 'relationship')
-
-    @declared_attr
-    def capability(cls):
-        return relationship.many_to_one(cls, 'capability')
+        """
+        Containing node (can be ``None``).
 
-    @declared_attr
-    def artifact(cls):
-        return relationship.many_to_one(cls, 'artifact')
+        :type: :class:`Node`
+        """
+        return relationship.many_to_one(cls, 'node')
 
     # endregion
 
-
-class AttributeBase(ParameterMixin):
-
-    __tablename__ = 'attribute'
-
     # region foreign keys
 
     @declared_attr
@@ -288,40 +445,52 @@ class AttributeBase(ParameterMixin):
 
     # endregion
 
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_template(cls):
-        return relationship.many_to_one(cls, 'node_template')
-
-    @declared_attr
-    def node(cls):
-        return relationship.many_to_one(cls, 'node')
-
-    # endregion
-
 
 class TypeBase(InstanceModelMixin):
     """
-    Represents a type and its children.
+    Type and its children. Can serve as the root for a type hierarchy.
     """
 
     __tablename__ = 'type'
 
-    __private_fields__ = ['parent_type_fk']
+    __private_fields__ = ('parent_type_fk',)
 
     variant = Column(Text, nullable=False)
-    description = Column(Text)
+
+    description = Column(Text, doc="""
+    Human-readable description.
+
+    :type: :obj:`basestring`
+    """)
+
     _role = Column(Text, name='role')
 
+    # region one_to_one relationships
+
     @declared_attr
     def parent(cls):
+        """
+        Parent type (will be ``None`` for the root of a type hierarchy).
+
+        :type: :class:`Type`
+        """
         return relationship.one_to_one_self(cls, 'parent_type_fk')
 
+    # endregion
+
+    # region one_to_many relationships
+
     @declared_attr
     def children(cls):
+        """
+        Children.
+
+        :type: [:class:`Type`]
+        """
         return relationship.one_to_many(cls, other_fk='parent_type_fk', self=True)
 
+    # endregion
+
     # region foreign keys
 
     @declared_attr
@@ -402,8 +571,9 @@ class TypeBase(InstanceModelMixin):
     @property
     def hierarchy(self):
         """
-        Return the type hierarchy.
-        :return:
+        Type hierarchy as a list beginning with this type and ending in the root.
+
+        :type: [:class:`Type`]
         """
         return [self] + (self.parent.hierarchy if self.parent else [])
 
@@ -414,9 +584,9 @@ class MetadataBase(TemplateModelMixin):
 
     This model is used by both service template and service instance elements.
 
-    :ivar name: Name
+    :ivar name: name
     :vartype name: basestring
-    :ivar value: Value
+    :ivar value: value
     :vartype value: basestring
     """
 


[04/15] incubator-ariatosca git commit: ARIA-291 Add ASCII art in ARIA CLI version command

Posted by em...@apache.org.
ARIA-291 Add ASCII art in ARIA CLI version command


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/807db308
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/807db308
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/807db308

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 807db3086671959ef12fe539c3215fbbaa0286f8
Parents: 668ddcb
Author: Ran Ziv <ra...@gigaspaces.com>
Authored: Sun Jun 25 17:04:43 2017 +0300
Committer: Ran Ziv <ra...@gigaspaces.com>
Committed: Sun Jun 25 17:32:45 2017 +0300

----------------------------------------------------------------------
 aria/cli/ascii_art.py | 24 ++++++++++++++++++++++++
 aria/cli/core/aria.py |  4 ++--
 2 files changed, 26 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/807db308/aria/cli/ascii_art.py
----------------------------------------------------------------------
diff --git a/aria/cli/ascii_art.py b/aria/cli/ascii_art.py
new file mode 100644
index 0000000..8a8b79f
--- /dev/null
+++ b/aria/cli/ascii_art.py
@@ -0,0 +1,24 @@
+# -*- coding: utf8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+ARIA_ASCII_ART = r"""
+     █████╗ ██████╗ ██╗ █████╗ 
+    ██╔══██╗██╔══██╗██║██╔══██╗
+    ███████║██████╔╝██║███████║
+    ██╔══██║██╔══██╗██║██╔══██║
+    ██║  ██║██║  ██║██║██║  ██║
+    ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═╝"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/807db308/aria/cli/core/aria.py
----------------------------------------------------------------------
diff --git a/aria/cli/core/aria.py b/aria/cli/core/aria.py
index 331caca..e5b3eb2 100644
--- a/aria/cli/core/aria.py
+++ b/aria/cli/core/aria.py
@@ -28,9 +28,9 @@ from ..env import (
 )
 from .. import defaults
 from .. import helptexts
+from ..ascii_art import ARIA_ASCII_ART
 from ..inputs import inputs_to_dict
 from ... import __version__
-from ... import aria_package_name
 from ...utils.exceptions import get_exception_as_string
 
 
@@ -97,7 +97,7 @@ def show_version(ctx, param, value):
     if not value:
         return
 
-    logger.info('{0} {1}'.format(aria_package_name, __version__))
+    logger.info('{0} v{1}'.format(ARIA_ASCII_ART, __version__))
     ctx.exit()
 
 


[02/15] incubator-ariatosca git commit: ARIA-290 Update Makefile for binary dist creation

Posted by em...@apache.org.
ARIA-290 Update Makefile for binary dist creation

Updated the Makefile to push required files for release
(LICENSE, NOTICE, DISCLAIMER) into the binary distribution
archive (wheel) automatically.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/51d0542c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/51d0542c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/51d0542c

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 51d0542c32611b6711415e79b49056729abf47d5
Parents: a75a3de
Author: Ran Ziv <ra...@gigaspaces.com>
Authored: Sun Jun 25 16:49:42 2017 +0300
Committer: Ran Ziv <ra...@gigaspaces.com>
Committed: Sun Jun 25 16:54:19 2017 +0300

----------------------------------------------------------------------
 Makefile | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/51d0542c/Makefile
----------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index f5f2e66..4884a65 100644
--- a/Makefile
+++ b/Makefile
@@ -59,6 +59,8 @@ test:
 
 dist: docs
 	python ./setup.py sdist bdist_wheel
+	# pushing LICENSE and additional files into the binary distribution archive
+	-find "$(DIST)" -type f -name '*.whl' -exec zip -u {} LICENSE NOTICE DISCLAIMER \;
 
 deploy:
 	pip install --upgrade "twine>=1.9.1"


[07/15] incubator-ariatosca git commit: ARIA-289 Don't attempt resuming a workflow which finished successfully

Posted by em...@apache.org.
ARIA-289 Don't attempt resuming a workflow which finished successfully


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/53dc64e4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/53dc64e4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/53dc64e4

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 53dc64e4c2c9c6fbba2c67c2f4b2d5edb0b36304
Parents: b1b1ee4
Author: max-orlov <ma...@gigaspaces.com>
Authored: Wed Jun 28 12:27:38 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Wed Jun 28 14:06:31 2017 +0300

----------------------------------------------------------------------
 README.rst                      | 2 +-
 aria/cli/commands/executions.py | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/53dc64e4/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index d4740cd..b9a8213 100644
--- a/README.rst
+++ b/README.rst
@@ -138,7 +138,7 @@ Subscribe by sending a mail to ``<group>-subscribe@ariatosca.incubator.apache.or
 lists `here <https://www.apache.org/foundation/mailinglists.html>`__.
 
 For past correspondence, see the
-`dev mailing list archive <http://mail-archives.apache.org/mod_mbox/incubator-ariatosca-dev/>`__.
+`dev mailing list archive <ht...@ariatosca.apache.org>`__.
 
 
 License

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/53dc64e4/aria/cli/commands/executions.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/executions.py b/aria/cli/commands/executions.py
index b337e84..9f56ccd 100644
--- a/aria/cli/commands/executions.py
+++ b/aria/cli/commands/executions.py
@@ -168,6 +168,14 @@ def resume(execution_id,
            logger):
     executor = DryExecutor() if dry else None  # use WorkflowRunner's default executor
 
+    execution = model_storage.execution.get(execution_id)
+    if execution.status != execution.status.CANCELLED:
+        logger.info("Can't resume execution {execution.id} - "
+                    "execution is in status {execution.status}. "
+                    "Can only resume executions in status {valid_status}"
+                    .format(execution=execution, valid_status=execution.status.CANCELLED))
+        return
+
     workflow_runner = \
         WorkflowRunner(
             model_storage, resource_storage, plugin_manager,


[08/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/definitions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/definitions.py b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
index 8564249..1bd0366 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/definitions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
@@ -42,7 +42,7 @@ class PropertyDefinition(ExtensiblePresentation):
     an entity defined in this specification (e.g., Node Types, Relationship Types, Capability Types,
     etc.). Properties are used by template authors to provide input values to TOSCA entities which
     indicate their "desired state" when they are instantiated. The value of a property can be
-    retrieved using the :code:`get_property` function within TOSCA Service Templates.
+    retrieved using the ``get_property`` function within TOSCA Service Templates.
 
     See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
     /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
@@ -55,7 +55,7 @@ class PropertyDefinition(ExtensiblePresentation):
         """
         The required data type for the property.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -63,7 +63,7 @@ class PropertyDefinition(ExtensiblePresentation):
         """
         The optional description for the property.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_field(bool, default=True)
@@ -71,7 +71,7 @@ class PropertyDefinition(ExtensiblePresentation):
         """
         An optional key that declares a property as required (true) or not (false).
 
-        :rtype: bool
+        :type: bool
         """
 
     @field_validator(data_value_validator)
@@ -81,7 +81,7 @@ class PropertyDefinition(ExtensiblePresentation):
         An optional key that may provide a value to be used as a default if not provided by another
         means.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str, default='supported', allowed=('supported', 'unsupported', 'experimental',
@@ -91,7 +91,7 @@ class PropertyDefinition(ExtensiblePresentation):
         """
         The optional status of the property relative to the specification or implementation.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_list_field(ConstraintClause)
@@ -99,7 +99,7 @@ class PropertyDefinition(ExtensiblePresentation):
         """
         The optional list of sequenced constraint clauses for the property.
 
-        :rtype: list of (str, :class:`ConstraintClause`)
+        :type: list of (str, :class:`ConstraintClause`)
         """
 
     @field_validator(entry_schema_validator)
@@ -109,7 +109,7 @@ class PropertyDefinition(ExtensiblePresentation):
         The optional key that is used to declare the name of the Datatype definition for entries of
         set types such as the TOSCA list or map.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @cachedmethod
@@ -128,7 +128,7 @@ class AttributeDefinition(ExtensiblePresentation):
     defined in this specification (e.g., a Node, Relationship or Capability Type). Specifically, it
     is used to expose the "actual state" of some property of a TOSCA entity after it has been
     deployed and instantiated (as set by the TOSCA orchestrator). Attribute values can be retrieved
-    via the :code:`get_attribute` function from the instance model and used as values to other
+    via the ``get_attribute`` function from the instance model and used as values to other
     entities within TOSCA Service Templates.
 
     See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
@@ -142,7 +142,7 @@ class AttributeDefinition(ExtensiblePresentation):
         """
         The required data type for the attribute.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -150,7 +150,7 @@ class AttributeDefinition(ExtensiblePresentation):
         """
         The optional description for the attribute.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @field_validator(data_value_validator)
@@ -163,7 +163,7 @@ class AttributeDefinition(ExtensiblePresentation):
         This value SHALL be type compatible with the type declared by the property definition's type
         keyname.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str, default='supported', allowed=('supported', 'unsupported', 'experimental',
@@ -172,7 +172,7 @@ class AttributeDefinition(ExtensiblePresentation):
         """
         The optional status of the attribute relative to the specification or implementation.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_validator(entry_schema_validator)
@@ -182,7 +182,7 @@ class AttributeDefinition(ExtensiblePresentation):
         The optional key that is used to declare the name of the Datatype definition for entries of
         set types such as the TOSCA list or map.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @cachedmethod
@@ -212,7 +212,7 @@ class ParameterDefinition(PropertyDefinition):
         Note: This keyname is required for a TOSCA Property definition, but is not for a TOSCA
         Parameter definition.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_validator(data_value_validator)
@@ -241,7 +241,7 @@ class OperationDefinition(ExtensiblePresentation):
         """
         The optional description string for the associated named operation.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_field(OperationImplementation)
@@ -250,7 +250,7 @@ class OperationDefinition(ExtensiblePresentation):
         The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR
         file).
 
-        :rtype: :class:`OperationImplementation`
+        :type: :class:`OperationImplementation`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -261,7 +261,7 @@ class OperationDefinition(ExtensiblePresentation):
         includes when interface definitions are included as part of a Requirement definition in a
         Node Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
 @allow_unknown_fields
@@ -284,7 +284,7 @@ class InterfaceDefinition(ExtensiblePresentation):
         """
         ARIA NOTE: This field is not mentioned in the spec, but is implied.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -295,13 +295,13 @@ class InterfaceDefinition(ExtensiblePresentation):
         includes when interface definitions are included as part of a Requirement definition in a
         Node Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_unknown_fields(OperationDefinition)
     def operations(self):
         """
-        :rtype: dict of str, :class:`OperationDefinition`
+        :type: {:obj:`basestring`: :class:`OperationDefinition`}
         """
 
     @cachedmethod
@@ -325,6 +325,10 @@ class InterfaceDefinition(ExtensiblePresentation):
 @short_form_field('type')
 @has_fields
 class RelationshipDefinition(ExtensiblePresentation):
+    """
+    Relationship definition.
+    """
+
     @field_validator(type_validator('relationship type', convert_shorthand_to_full_type_name,
                                     'relationship_types'))
     @primitive_field(str, required=True)
@@ -333,7 +337,7 @@ class RelationshipDefinition(ExtensiblePresentation):
         The optional reserved keyname used to provide the name of the Relationship Type for the
         requirement definition's relationship keyname.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_dict_field(InterfaceDefinition)
@@ -343,7 +347,7 @@ class RelationshipDefinition(ExtensiblePresentation):
         the corresponding Relationship Type in order to declare additional Property definitions for
         these interfaces or operations of these interfaces.
 
-        :rtype: list of :class:`InterfaceDefinition`
+        :type: list of :class:`InterfaceDefinition`
         """
 
     @cachedmethod
@@ -375,7 +379,7 @@ class RequirementDefinition(ExtensiblePresentation):
         The required reserved keyname used that can be used to provide the name of a valid
         Capability Type that can fulfill the requirement.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_validator(type_validator('node type', convert_shorthand_to_full_type_name, 'node_types'))
@@ -385,7 +389,7 @@ class RequirementDefinition(ExtensiblePresentation):
         The optional reserved keyname used to provide the name of a valid Node Type that contains
         the capability definition that can be used to fulfill the requirement.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(RelationshipDefinition)
@@ -394,7 +398,7 @@ class RequirementDefinition(ExtensiblePresentation):
         The optional reserved keyname used to provide the name of a valid Relationship Type to
         construct when fulfilling the requirement.
 
-        :rtype: :class:`RelationshipDefinition`
+        :type: :class:`RelationshipDefinition`
         """
 
     @field_getter(data_type_class_getter(Range))
@@ -405,7 +409,7 @@ class RequirementDefinition(ExtensiblePresentation):
 
         Note: the keyword UNBOUNDED is also supported to represent any positive integer.
 
-        :rtype: :class:`Range`
+        :type: :class:`Range`
         """
 
     @cachedmethod
@@ -437,7 +441,7 @@ class CapabilityDefinition(ExtensiblePresentation):
         """
         The required name of the Capability Type the capability definition is based upon.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -445,7 +449,7 @@ class CapabilityDefinition(ExtensiblePresentation):
         """
         The optional description of the Capability definition.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -453,7 +457,7 @@ class CapabilityDefinition(ExtensiblePresentation):
         """
         An optional list of property definitions for the Capability definition.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_field(AttributeDefinition)
@@ -461,7 +465,7 @@ class CapabilityDefinition(ExtensiblePresentation):
         """
         An optional list of attribute definitions for the Capability definition.
 
-        :rtype: dict of str, :class:`AttributeDefinition`
+        :type: {:obj:`basestring`: :class:`AttributeDefinition`}
         """
 
     @field_validator(list_type_validator('node type', convert_shorthand_to_full_type_name,
@@ -472,7 +476,7 @@ class CapabilityDefinition(ExtensiblePresentation):
         An optional list of one or more valid names of Node Types that are supported as valid
         sources of any relationship established to the declared Capability Type.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @field_getter(data_type_class_getter(Range))
@@ -481,14 +485,15 @@ class CapabilityDefinition(ExtensiblePresentation):
         """
         The optional minimum and maximum occurrences for the capability. By default, an exported
         Capability should allow at least one relationship to be formed with it with a maximum of
-        :code:`UNBOUNDED` relationships.
+        ``UNBOUNDED`` relationships.
 
-        Note: the keyword :code:`UNBOUNDED` is also supported to represent any positive integer.
+        Note: the keyword ``UNBOUNDED`` is also supported to represent any positive integer.
 
-        ARIA NOTE: The spec seems wrong here: the implied default should be [0,UNBOUNDED], not
-        [1,UNBOUNDED], otherwise it would imply that at 1 least one relationship *must* be formed.
+        ARIA NOTE: The spec seems wrong here: the implied default should be ``[0,UNBOUNDED]``, not
+        ``[1,UNBOUNDED]``, otherwise it would imply that at 1 least one relationship *must* be
+        formed.
 
-        :rtype: :class:`Range`
+        :type: :class:`Range`
         """
 
     @cachedmethod

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/filters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/filters.py b/extensions/aria_extension_tosca/simple_v1_0/filters.py
index 838b505..6db140d 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/filters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/filters.py
@@ -24,6 +24,10 @@ from .presentation.field_validators import (node_filter_properties_validator,
 
 @has_fields
 class CapabilityFilter(ExtensiblePresentation):
+    """
+    Capability filter.
+    """
+
     @object_sequenced_list_field(ConstraintClause)
     def properties(self):
         pass
@@ -69,7 +73,7 @@ class NodeFilter(ExtensiblePresentation):
         /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
         #DEFN_ELEMENT_PROPERTY_FILTER_DEFN>`__
 
-        :rtype: list of (str, :class:`ConstraintClause`)
+        :type: list of (str, :class:`ConstraintClause`)
         """
 
     @field_validator(node_filter_capabilities_validator)
@@ -80,7 +84,7 @@ class NodeFilter(ExtensiblePresentation):
         matching TOSCA entities (e.g., Node Template, Node Type, Capability Types, etc.) based upon
         their capabilities' property definitions' values.
 
-        :rtype: list of (str, :class:`CapabilityDefinition`)
+        :type: list of (str, :class:`CapabilityDefinition`)
         """
 
     @cachedmethod

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/misc.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/misc.py b/extensions/aria_extension_tosca/simple_v1_0/misc.py
index 74eba18..f4d43ac 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/misc.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py
@@ -39,6 +39,8 @@ from .presentation.types import (convert_shorthand_to_full_type_name,
 @implements_specification('3.5.1', 'tosca-simple-1.0')
 class Description(AsIsPresentation):
     """
+    Human-readable description.
+
     See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
     /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
     #DEFN_ELEMENT_DESCRIPTION>`__
@@ -55,6 +57,10 @@ class Description(AsIsPresentation):
 @has_fields
 @implements_specification('3.9.3.2', 'tosca-simple-1.0')
 class MetaData(ExtensiblePresentation):
+    """
+    Meta data.
+    """
+
     @primitive_field(str)
     @implements_specification('3.9.3.3', 'tosca-simple-1.0')
     def template_name(self):
@@ -82,7 +88,7 @@ class MetaData(ExtensiblePresentation):
     @primitive_dict_unknown_fields()
     def custom(self):
         """
-        :rtype: dict
+        :type: dict
         """
 
 @short_form_field('url')
@@ -103,7 +109,7 @@ class Repository(ExtensiblePresentation):
         """
         The optional description for the repository.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_field(str, required=True)
@@ -111,7 +117,7 @@ class Repository(ExtensiblePresentation):
         """
         The required URL or network address used to access the repository.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field()
@@ -119,7 +125,7 @@ class Repository(ExtensiblePresentation):
         """
         The optional Credential used to authorize access to the repository.
 
-        :rtype: tosca.datatypes.Credential
+        :type: tosca.datatypes.Credential
         """
 
     @cachedmethod
@@ -145,7 +151,7 @@ class Import(ExtensiblePresentation):
         """
         The required symbolic name for the imported file.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str)
@@ -154,7 +160,7 @@ class Import(ExtensiblePresentation):
         The optional symbolic name of the repository definition where the imported file can be found
         as a string.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str)
@@ -163,7 +169,7 @@ class Import(ExtensiblePresentation):
         The optional namespace URI to that will be applied to type definitions found within the
         imported file as a string.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str)
@@ -173,7 +179,7 @@ class Import(ExtensiblePresentation):
         forming a qualified name (i.e., qname) when referencing type definitions from the imported
         file.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
 @has_fields
@@ -233,7 +239,7 @@ class ConstraintClause(ExtensiblePresentation):
         Constrains a property or parameter to a value in range of (inclusive) the two values
         declared.
 
-        Note: subclasses or templates of types that declare a property with the :code:`in_range`
+        Note: subclasses or templates of types that declare a property with the ``in_range``
         constraint MAY only further restrict the range specified by the parent type.
         """
 
@@ -300,19 +306,19 @@ class EntrySchema(ExtensiblePresentation):
     @primitive_field(str, required=True)
     def type(self):
         """
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
     def description(self):
         """
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_list_field(ConstraintClause)
     def constraints(self):
         """
-        :rtype: list of (str, :class:`ConstraintClause`)
+        :type: list of (str, :class:`ConstraintClause`)
         """
 
     @cachedmethod
@@ -326,13 +332,17 @@ class EntrySchema(ExtensiblePresentation):
 @short_form_field('primary')
 @has_fields
 class OperationImplementation(ExtensiblePresentation):
+    """
+    Operation implementation.
+    """
+
     @primitive_field(str)
     def primary(self):
         """
         The optional implementation artifact name (i.e., the primary script file name within a
         TOSCA CSAR file).
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_list_field(str)
@@ -342,10 +352,14 @@ class OperationImplementation(ExtensiblePresentation):
         which are referenced by the primary implementation artifact (e.g., a library the script
         installs or a secondary script).
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
 class SubstitutionMappingsRequirement(AsIsPresentation):
+    """
+    Substitution mapping for requirement.
+    """
+
     @property
     @cachedmethod
     def node_template(self):
@@ -361,6 +375,10 @@ class SubstitutionMappingsRequirement(AsIsPresentation):
         validate_subtitution_mappings_requirement(context, self)
 
 class SubstitutionMappingsCapability(AsIsPresentation):
+    """
+    Substitution mapping for capability.
+    """
+
     @property
     @cachedmethod
     def node_template(self):
@@ -378,23 +396,27 @@ class SubstitutionMappingsCapability(AsIsPresentation):
 @has_fields
 @implements_specification('2.10', 'tosca-simple-1.0')
 class SubstitutionMappings(ExtensiblePresentation):
+    """
+    Substitution mappings.
+    """
+
     @field_validator(type_validator('node type', convert_shorthand_to_full_type_name, 'node_types'))
     @primitive_field(str, required=True)
     def node_type(self):
         """
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_dict_field(SubstitutionMappingsRequirement)
     def requirements(self):
         """
-        :rtype: dict of str, :class:`SubstitutionMappingsRequirement`
+        :type: {:obj:`basestring`: :class:`SubstitutionMappingsRequirement`}
         """
 
     @object_dict_field(SubstitutionMappingsCapability)
     def capabilities(self):
         """
-        :rtype: dict of str, :class:`SubstitutionMappingsCapability`
+        :type: {:obj:`basestring`: :class:`SubstitutionMappingsCapability`}
         """
 
     @cachedmethod

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 5813ccf..957dc7b 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -484,7 +484,6 @@ def create_substitution_template_model(context, service_template, substitution_m
                 node_template_model.capability_templates[capability.capability]
             model.mappings[name] = \
                 SubstitutionTemplateMapping(name=name,
-                                            node_template=node_template_model,
                                             capability_template=capability_template_model)
 
     requirements = substitution_mappings.requirements
@@ -499,7 +498,6 @@ def create_substitution_template_model(context, service_template, substitution_m
                     break
             model.mappings[name] = \
                 SubstitutionTemplateMapping(name=name,
-                                            node_template=node_template_model,
                                             requirement_template=requirement_template_model)
 
     return model

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
index a90a9fc..d75e723 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
@@ -26,8 +26,8 @@ from .parameters import (convert_parameter_definitions_to_values, merge_raw_para
 
 def get_inherited_valid_source_types(context, presentation):
     """
-    If we haven't set the :code:`valid_source_types` fields, uses that value from our parent, if
-    we have one (recursively).
+    If we haven't set the ``valid_source_types`` fields, uses that value from our parent, if we have
+    one (recursively).
     """
 
     valid_source_types = presentation.valid_source_types

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
index b86e8eb..bd9037f 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
@@ -19,7 +19,7 @@
 
 def get_default_raw_from_copy(presentation, field_name):
     """
-    Used for the :code:`_get_default_raw` field hook.
+    Used for the ``_get_default_raw`` field hook.
     """
 
     copy = presentation._raw.get('copy')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
index c0d79e5..ba94c70 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
@@ -55,7 +55,7 @@ def get_inherited_constraints(context, presentation):
 def coerce_data_type_value(context, presentation, data_type, entry_schema, constraints, value, # pylint: disable=unused-argument
                            aspect):
     """
-    Handles the :code:`_coerce_data()` hook for complex data types.
+    Handles the ``_coerce_data()`` hook for complex data types.
 
     There are two kinds of handling:
 
@@ -383,7 +383,7 @@ def coerce_value(context, presentation, the_type, entry_schema, constraints, val
 
     Supports both complex data types and primitives.
 
-    Data types can use the :code:`coerce_value` extension to hook their own specialized function.
+    Data types can use the ``coerce_value`` extension to hook their own specialized function.
     If the extension is present, we will delegate to that hook.
     """
 
@@ -454,10 +454,10 @@ def coerce_to_data_type_class(context, presentation, cls, entry_schema, constrai
     Returns the value after it's coerced to a data type class, reporting validation errors if it
     cannot be coerced. Constraints will be applied after coersion.
 
-    Will either call a :code:`_create` static function in the class, or instantiate it using a
-    constructor if :code:`_create` is not available.
+    Will either call a ``_create`` static function in the class, or instantiate it using a
+    constructor if ``_create`` is not available.
 
-    This will usually be called by a :code:`coerce_value` extension hook in a :class:`DataType`.
+    This will usually be called by a ``coerce_value`` extension hook in a :class:`DataType`.
     """
 
     try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
index 7025213..590c6a0 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
@@ -34,7 +34,7 @@ from aria.modeling.functions import (Function, Evaluation)
 @implements_specification('4.3.1', 'tosca-simple-1.0')
 class Concat(Function):
     """
-    The :code:`concat` function is used to concatenate two or more string values within a TOSCA
+    The ``concat`` function is used to concatenate two or more string values within a TOSCA
     service template.
     """
 
@@ -76,7 +76,7 @@ class Concat(Function):
 @implements_specification('4.3.2', 'tosca-simple-1.0')
 class Token(Function):
     """
-    The :code:`token` function is used within a TOSCA service template on a string to parse out
+    The ``token`` function is used within a TOSCA service template on a string to parse out
     (tokenize) substrings separated by one or more token characters within a larger string.
     """
 
@@ -127,7 +127,7 @@ class Token(Function):
 @implements_specification('4.4.1', 'tosca-simple-1.0')
 class GetInput(Function):
     """
-    The :code:`get_input` function is used to retrieve the values of properties declared within the
+    The ``get_input`` function is used to retrieve the values of properties declared within the
     inputs section of a TOSCA Service Template.
     """
 
@@ -170,7 +170,7 @@ class GetInput(Function):
 @implements_specification('4.4.2', 'tosca-simple-1.0')
 class GetProperty(Function):
     """
-    The :code:`get_property` function is used to retrieve property values between modelable entities
+    The ``get_property`` function is used to retrieve property values between modelable entities
     defined in the same service template.
     """
 
@@ -238,7 +238,7 @@ class GetProperty(Function):
 @implements_specification('4.5.1', 'tosca-simple-1.0')
 class GetAttribute(Function):
     """
-    The :code:`get_attribute` function is used to retrieve the values of named attributes declared
+    The ``get_attribute`` function is used to retrieve the values of named attributes declared
     by the referenced node or relationship template name.
     """
 
@@ -285,7 +285,7 @@ class GetAttribute(Function):
 @implements_specification('4.6.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
 class GetOperationOutput(Function):
     """
-    The :code:`get_operation_output` function is used to retrieve the values of variables exposed /
+    The ``get_operation_output`` function is used to retrieve the values of variables exposed /
     exported from an interface operation.
     """
 
@@ -331,7 +331,7 @@ class GetOperationOutput(Function):
 @implements_specification('4.7.1', 'tosca-simple-1.0')
 class GetNodesOfType(Function):
     """
-    The :code:`get_nodes_of_type` function can be used to retrieve a list of all known instances of
+    The ``get_nodes_of_type`` function can be used to retrieve a list of all known instances of
     nodes of the declared Node Type.
     """
 
@@ -367,7 +367,7 @@ class GetNodesOfType(Function):
 @implements_specification('4.8.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
 class GetArtifact(Function):
     """
-    The :code:`get_artifact` function is used to retrieve artifact location between modelable
+    The ``get_artifact`` function is used to retrieve artifact location between modelable
     entities defined in the same service template.
     """
 
@@ -574,7 +574,7 @@ def get_hosts(container_holder, name, locator):
     using this reference (i.e., as identified by its HostedOn relationship).
 
     Specifically, TOSCA orchestrators that encounter this keyword when evaluating the get_attribute
-    or :code:`get_property` functions SHALL search each node along the "HostedOn" relationship chain
+    or ``get_property`` functions SHALL search each node along the "HostedOn" relationship chain
     starting at the immediate node that hosts the node where the function was evaluated (and then
     that node's host node, and so forth) until a match is found or the "HostedOn" relationship chain
     ends.

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
index a2fd6ee..63bc02f 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/extensible.py
@@ -19,7 +19,7 @@ from aria.parser.presentation import (Presentation, has_fields, primitive_dict_f
 @has_fields
 class ExtensiblePresentation(Presentation):
     """
-    A presentation that supports an optional :code:`_extensions` dict field.
+    A presentation that supports an optional ``_extensions`` dict field.
     """
 
     @primitive_dict_field()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
index d7b03ae..be80702 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
@@ -33,7 +33,7 @@ def copy_validator(template_type_name, templates_dict_name):
     """
     Makes sure that the field refers to an existing template defined in the root presenter.
 
-    Use with the :func:`field_validator` decorator for the :code:`copy` field in
+    Use with the :func:`field_validator` decorator for the ``copy`` field in
     :class:`NodeTemplate` and :class:`RelationshipTemplate`.
     """
 
@@ -64,7 +64,7 @@ def data_type_validator(type_name='data type'):
     """
     Makes sure that the field refers to a valid data type, whether complex or primitive.
 
-    Used with the :func:`field_validator` decorator for the :code:`type` fields in
+    Used with the :func:`field_validator` decorator for the ``type`` fields in
     :class:`PropertyDefinition`, :class:`AttributeDefinition`, :class:`ParameterDefinition`,
     and :class:`EntrySchema`.
 
@@ -103,10 +103,10 @@ def data_type_validator(type_name='data type'):
 
 def entry_schema_validator(field, presentation, context):
     """
-    According to whether the data type supports :code:`entry_schema` (e.g., it is or inherits from
+    According to whether the data type supports ``entry_schema`` (e.g., it is or inherits from
     list or map), make sure that we either have or don't have a valid data type value.
 
-    Used with the :func:`field_validator` decorator for the :code:`entry_schema` field in
+    Used with the :func:`field_validator` decorator for the ``entry_schema`` field in
     :class:`PropertyDefinition` and :class:`AttributeDefinition`.
     """
 
@@ -145,7 +145,7 @@ def data_value_validator(field, presentation, context):
     """
     Makes sure that the field contains a valid value according to data type and constraints.
 
-    Used with the :func:`field_validator` decorator for the :code:`default` field in
+    Used with the :func:`field_validator` decorator for the ``default`` field in
     :class:`PropertyDefinition` and :class:`AttributeDefinition`.
     """
 
@@ -172,7 +172,7 @@ def data_type_derived_from_validator(field, presentation, context):
     """
     Makes sure that the field refers to a valid parent data type (complex or primitive).
 
-    Used with the :func:`field_validator` decorator for the :code:`derived_from` field in
+    Used with the :func:`field_validator` decorator for the ``derived_from`` field in
     :class:`DataType`.
     """
 
@@ -201,7 +201,7 @@ def data_type_properties_validator(field, presentation, context):
     """
     Makes sure that we do not have properties if we have a primitive ancestor.
 
-    Used with the :func:`field_validator` decorator for the :code:`properties` field in
+    Used with the :func:`field_validator` decorator for the ``properties`` field in
     :class:`DataType`.
     """
 
@@ -241,7 +241,7 @@ def constraint_clause_in_range_validator(field, presentation, context):
     valid value for the container type, and that the upper bound is either "UNBOUNDED" or a valid
     value for the container type.
 
-    Used with the :func:`field_validator` decorator for the :code:`in_range` field in
+    Used with the :func:`field_validator` decorator for the ``in_range`` field in
     :class:`ConstraintClause`.
     """
 
@@ -278,7 +278,7 @@ def constraint_clause_valid_values_validator(field, presentation, context):
     """
     Makes sure that the value is a list of valid values for the container type.
 
-    Used with the :func:`field_validator` decorator for the :code:`valid_values` field in
+    Used with the :func:`field_validator` decorator for the ``valid_values`` field in
     :class:`ConstraintClause`.
     """
 
@@ -294,7 +294,7 @@ def constraint_clause_pattern_validator(field, presentation, context):
     """
     Makes sure that the value is a valid regular expression.
 
-    Used with the :func:`field_validator` decorator for the :code:`pattern` field in
+    Used with the :func:`field_validator` decorator for the ``pattern`` field in
     :class:`ConstraintClause`.
     """
 
@@ -324,7 +324,7 @@ def node_template_or_type_validator(field, presentation, context):
     """
     Makes sure that the field refers to either a node template or a node type.
 
-    Used with the :func:`field_validator` decorator for the :code:`node` field in
+    Used with the :func:`field_validator` decorator for the ``node`` field in
     :class:`RequirementAssignment`.
     """
 
@@ -343,11 +343,11 @@ def node_template_or_type_validator(field, presentation, context):
 def capability_definition_or_type_validator(field, presentation, context):
     """
     Makes sure refers to either a capability assignment name in the node template referred to by the
-    :code:`node` field or a general capability type.
+    ``node`` field or a general capability type.
 
-    If the value refers to a capability type, make sure the :code:`node` field was not assigned.
+    If the value refers to a capability type, make sure the ``node`` field was not assigned.
 
-    Used with the :func:`field_validator` decorator for the :code:`capability` field in
+    Used with the :func:`field_validator` decorator for the ``capability`` field in
     :class:`RequirementAssignment`.
     """
 
@@ -385,7 +385,7 @@ def node_filter_validator(field, presentation, context):
     """
     Makes sure that the field has a value only if "node" refers to a node type.
 
-    Used with the :func:`field_validator` decorator for the :code:`node_filter` field in
+    Used with the :func:`field_validator` decorator for the ``node_filter`` field in
     :class:`RequirementAssignment`.
     """
 
@@ -409,7 +409,7 @@ def relationship_template_or_type_validator(field, presentation, context):
     """
     Makes sure that the field refers to either a relationship template or a relationship type.
 
-    Used with the :func:`field_validator` decorator for the :code:`type` field in
+    Used with the :func:`field_validator` decorator for the ``type`` field in
     :class:`RelationshipAssignment`.
     """
 
@@ -434,7 +434,7 @@ def list_node_type_or_group_type_validator(field, presentation, context):
     """
     Makes sure that the field's elements refer to either node types or a group types.
 
-    Used with the :func:`field_validator` decorator for the :code:`targets` field in
+    Used with the :func:`field_validator` decorator for the ``targets`` field in
     :class:`PolicyType`.
     """
 
@@ -458,7 +458,7 @@ def policy_targets_validator(field, presentation, context):
     Makes sure that the field's elements refer to either node templates or groups, and that
     they match the node types and group types declared in the policy type.
 
-    Used with the :func:`field_validator` decorator for the :code:`targets` field in
+    Used with the :func:`field_validator` decorator for the ``targets`` field in
     :class:`PolicyTemplate`.
     """
 
@@ -514,7 +514,7 @@ def node_filter_properties_validator(field, presentation, context):
     """
     Makes sure that the field's elements refer to defined properties in the target node type.
 
-    Used with the :func:`field_validator` decorator for the :code:`properties` field in
+    Used with the :func:`field_validator` decorator for the ``properties`` field in
     :class:`NodeFilter`.
     """
 
@@ -537,7 +537,7 @@ def node_filter_capabilities_validator(field, presentation, context):
     Makes sure that the field's elements refer to defined capabilities and properties in the target
     node type.
 
-    Used with the :func:`field_validator` decorator for the :code:`capabilities` field in
+    Used with the :func:`field_validator` decorator for the ``capabilities`` field in
     :class:`NodeFilter`.
     """
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
index 088a246..610e4a0 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
@@ -17,11 +17,11 @@ def convert_shorthand_to_full_type_name(context, name, types_dict): # pylint: di
     """
     Converts a shorthand type name to its full type name, or else returns it unchanged.
 
-    Works by checking for :code:`shorthand_name` in the types' :code:`_extensions` field. See also
+    Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also
     :class:`aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`.
 
-    Can be used as the conversion function argument in :code:`type_validator` and
-    :code:`derived_from_validator`.
+    Can be used as the conversion function argument in ``type_validator`` and
+    ``derived_from_validator``.
     """
 
     if (name is not None) and types_dict and (name not in types_dict):
@@ -35,11 +35,11 @@ def get_type_by_full_or_shorthand_name(context, name, *types_dict_names):
     """
     Gets a type either by its full name or its shorthand name.
 
-    Works by checking for :code:`shorthand_name` in the types' :code:`_extensions` field. See also
-    :class:`aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`.
+    Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also
+    :class:`~aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`.
 
     The arguments from the third onwards are used to locate a nested field under
-    :code:`service_template` under the root presenter.
+    ``service_template`` under the root presenter.
     """
 
     if name is not None:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/presenter.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
index f64078f..394e303 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presenter.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
@@ -27,9 +27,9 @@ class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name,abstrac
     ARIA presenter for the `TOSCA Simple Profile v1.0 cos01 <http://docs.oasis-open.org/tosca
     /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html>`__.
 
-    Supported :code:`tosca_definitions_version` values:
+    Supported ``tosca_definitions_version`` values:
 
-    * :code:`tosca_simple_yaml_1_0`
+    * ``tosca_simple_yaml_1_0``
     """
 
     DSL_VERSIONS = ('tosca_simple_yaml_1_0',)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/templates.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/templates.py b/extensions/aria_extension_tosca/simple_v1_0/templates.py
index 123a00e..285e496 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/templates.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/templates.py
@@ -60,7 +60,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         The required name of the Node Type the Node Template is based upon.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -68,7 +68,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional description for the Node Template.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_list_field(str)
@@ -77,7 +77,7 @@ class NodeTemplate(ExtensiblePresentation):
         An optional list of directive values to provide processing instructions to orchestrators and
         tooling.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @object_dict_field(PropertyAssignment)
@@ -85,7 +85,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional list of property value assignments for the Node Template.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @object_dict_field(AttributeAssignment)
@@ -93,7 +93,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional list of attribute value assignments for the Node Template.
 
-        :rtype: dict of str, :class:`AttributeAssignment`
+        :type: {:obj:`basestring`: :class:`AttributeAssignment`}
         """
 
     @object_sequenced_list_field(RequirementAssignment)
@@ -101,7 +101,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional sequenced list of requirement assignments for the Node Template.
 
-        :rtype: list of (str, :class:`RequirementAssignment`)
+        :type: list of (str, :class:`RequirementAssignment`)
         """
 
     @object_dict_field(CapabilityAssignment)
@@ -109,7 +109,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional list of capability assignments for the Node Template.
 
-        :rtype: dict of str, :class:`CapabilityAssignment`
+        :type: {:obj:`basestring`: :class:`CapabilityAssignment`}
         """
 
     @object_dict_field(InterfaceAssignment)
@@ -117,7 +117,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional list of named interface definitions for the Node Template.
 
-        :rtype: dict of str, :class:`InterfaceAssignment`
+        :type: {:obj:`basestring`: :class:`InterfaceAssignment`}
         """
 
     @object_dict_field(ArtifactAssignment)
@@ -125,7 +125,7 @@ class NodeTemplate(ExtensiblePresentation):
         """
         An optional list of named artifact definitions for the Node Template.
 
-        :rtype: dict of str, :class:`ArtifactAssignment`
+        :type: {:obj:`basestring`: :class:`ArtifactAssignment`}
         """
 
     @object_field(NodeFilter)
@@ -134,7 +134,7 @@ class NodeTemplate(ExtensiblePresentation):
         The optional filter definition that TOSCA orchestrators would use to select the correct
         target node. This keyname is only valid if the directive has the value of "selectable" set.
 
-        :rtype: :class:`NodeFilter`
+        :type: :class:`NodeFilter`
         """
 
     @field_validator(copy_validator('node template', 'node_templates'))
@@ -144,7 +144,7 @@ class NodeTemplate(ExtensiblePresentation):
         The optional (symbolic) name of another node template to copy into (all keynames and values)
         and use as a basis for this node template.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @cachedmethod
@@ -223,7 +223,7 @@ class RelationshipTemplate(ExtensiblePresentation):
         """
         The required name of the Relationship Type the Relationship Template is based upon.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -231,7 +231,7 @@ class RelationshipTemplate(ExtensiblePresentation):
         """
         An optional description for the Relationship Template.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -239,7 +239,7 @@ class RelationshipTemplate(ExtensiblePresentation):
         """
         An optional list of property assignments for the Relationship Template.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @object_dict_field(AttributeAssignment)
@@ -247,7 +247,7 @@ class RelationshipTemplate(ExtensiblePresentation):
         """
         An optional list of attribute assignments for the Relationship Template.
 
-        :rtype: dict of str, :class:`AttributeAssignment`
+        :type: {:obj:`basestring`: :class:`AttributeAssignment`}
         """
 
     @object_dict_field(InterfaceAssignment)
@@ -257,7 +257,7 @@ class RelationshipTemplate(ExtensiblePresentation):
 
         ARIA NOTE: Spec is wrong here, should be Relationship Template.
 
-        :rtype: dict of str, :class:`InterfaceAssignment`
+        :type: {:obj:`basestring`: :class:`InterfaceAssignment`}
         """
 
     @field_validator(copy_validator('relationship template', 'relationship_templates'))
@@ -267,7 +267,7 @@ class RelationshipTemplate(ExtensiblePresentation):
         The optional (symbolic) name of another relationship template to copy into (all keynames and
         values) and use as a basis for this relationship template.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @cachedmethod
@@ -319,7 +319,7 @@ class GroupTemplate(ExtensiblePresentation):
         """
         The required name of the group type the group definition is based upon.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -327,7 +327,7 @@ class GroupTemplate(ExtensiblePresentation):
         """
         The optional description for the group definition.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -335,7 +335,7 @@ class GroupTemplate(ExtensiblePresentation):
         """
         An optional list of property value assignments for the group definition.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @field_validator(list_type_validator('node template', 'topology_template', 'node_templates'))
@@ -345,7 +345,7 @@ class GroupTemplate(ExtensiblePresentation):
         The optional list of one or more node template names that are members of this group
         definition.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @object_dict_field(InterfaceAssignment)
@@ -353,7 +353,7 @@ class GroupTemplate(ExtensiblePresentation):
         """
         An optional list of named interface definitions for the group definition.
 
-        :rtype: dict of str, :class:`InterfaceDefinition`
+        :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
         """
 
     @cachedmethod
@@ -392,7 +392,7 @@ class PolicyTemplate(ExtensiblePresentation):
         """
         The required name of the policy type the policy definition is based upon.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -400,7 +400,7 @@ class PolicyTemplate(ExtensiblePresentation):
         """
         The optional description for the policy definition.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -408,7 +408,7 @@ class PolicyTemplate(ExtensiblePresentation):
         """
         An optional list of property value assignments for the policy definition.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`
         """
 
     @field_validator(policy_targets_validator)
@@ -417,7 +417,7 @@ class PolicyTemplate(ExtensiblePresentation):
         """
         An optional list of valid Node Templates or Groups the Policy can be applied to.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @cachedmethod
@@ -444,7 +444,7 @@ class TopologyTemplate(ExtensiblePresentation):
     This section defines the topology template of a cloud application. The main ingredients of the
     topology template are node templates representing components of the application and relationship
     templates representing links between the components. These elements are defined in the nested
-    :code:`node_templates` section and the nested relationship_templates sections, respectively.
+    ``node_templates`` section and the nested relationship_templates sections, respectively.
     Furthermore, a topology template allows for defining input parameters, output parameters as well
     as grouping of node templates.
 
@@ -458,7 +458,7 @@ class TopologyTemplate(ExtensiblePresentation):
         """
         The optional description for the Topology Template.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(ParameterDefinition)
@@ -467,7 +467,7 @@ class TopologyTemplate(ExtensiblePresentation):
         An optional list of input parameters (i.e., as parameter definitions) for the Topology
         Template.
 
-        :rtype: dict of str, :class:`ParameterDefinition`
+        :type: {:obj:`basestring`: :class:`ParameterDefinition`}
         """
 
     @object_dict_field(NodeTemplate)
@@ -475,7 +475,7 @@ class TopologyTemplate(ExtensiblePresentation):
         """
         An optional list of node template definitions for the Topology Template.
 
-        :rtype: dict of str, :class:`NodeTemplate`
+        :type: {:obj:`basestring`: :class:`NodeTemplate`}
         """
 
     @object_dict_field(RelationshipTemplate)
@@ -483,7 +483,7 @@ class TopologyTemplate(ExtensiblePresentation):
         """
         An optional list of relationship templates for the Topology Template.
 
-        :rtype: dict of str, :class:`RelationshipTemplate`
+        :type: {:obj:`basestring`: :class:`RelationshipTemplate`}
         """
 
     @object_dict_field(GroupTemplate)
@@ -500,7 +500,7 @@ class TopologyTemplate(ExtensiblePresentation):
         """
         An optional list of Policy definitions for the Topology Template.
 
-        :rtype: dict of str, :class:`PolicyTemplate`
+        :type: {:obj:`basestring`: :class:`PolicyTemplate`}
         """
 
     @object_dict_field(ParameterDefinition)
@@ -509,7 +509,7 @@ class TopologyTemplate(ExtensiblePresentation):
         An optional list of output parameters (i.e., as parameter definitions) for the Topology
         Template.
 
-        :rtype: dict of str, :class:`ParameterDefinition`
+        :type: {:obj:`basestring`: :class:`ParameterDefinition`}
         """
 
     @object_field(SubstitutionMappings)
@@ -551,6 +551,8 @@ class TopologyTemplate(ExtensiblePresentation):
 @implements_specification('3.9', 'tosca-simple-1.0')
 class ServiceTemplate(ExtensiblePresentation):
     """
+    Servicate template.
+
     See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
     /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
     #DEFN_ELEMENT_SERVICE_TEMPLATE>`__.
@@ -567,7 +569,7 @@ class ServiceTemplate(ExtensiblePresentation):
         /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
         #_Toc379455047>`__
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(MetaData)
@@ -580,7 +582,7 @@ class ServiceTemplate(ExtensiblePresentation):
         /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
         #_Toc379455048>`__
 
-        :rtype: :class:`MetaData`
+        :type: :class:`MetaData`
         """
 
     @object_field(Description)
@@ -589,7 +591,7 @@ class ServiceTemplate(ExtensiblePresentation):
         """
         Declares a description for this Service Template and its contents.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_field()
@@ -613,7 +615,7 @@ class ServiceTemplate(ExtensiblePresentation):
         the service template along with their addresses and necessary credential information used to
         connect to them in order to retrieve the artifacts.
 
-        :rtype: dict of str, :class:`Repository`
+        :type: {:obj:`basestring`: :class:`Repository`}
         """
 
     @object_list_field(Import)
@@ -623,7 +625,7 @@ class ServiceTemplate(ExtensiblePresentation):
         Declares import statements external TOSCA Definitions documents. For example, these may be
         file location or URIs relative to the service template file within the same TOSCA CSAR file.
 
-        :rtype: list of :class:`Import`
+        :type: list of :class:`Import`
         """
 
     @object_dict_field(ArtifactType)
@@ -633,7 +635,7 @@ class ServiceTemplate(ExtensiblePresentation):
         This section contains an optional list of artifact type definitions for use in the service
         template.
 
-        :rtype: dict of str, :class:`ArtifactType`
+        :type: {:obj:`basestring`: :class:`ArtifactType`}
         """
 
     @object_dict_field(DataType)
@@ -642,7 +644,7 @@ class ServiceTemplate(ExtensiblePresentation):
         """
         Declares a list of optional TOSCA Data Type definitions.
 
-        :rtype: dict of str, :class:`DataType`
+        :type: {:obj:`basestring`: :class:`DataType`}
         """
 
     @object_dict_field(CapabilityType)
@@ -652,7 +654,7 @@ class ServiceTemplate(ExtensiblePresentation):
         This section contains an optional list of capability type definitions for use in the service
         template.
 
-        :rtype: dict of str, :class:`CapabilityType`
+        :type: {:obj:`basestring`: :class:`CapabilityType`}
         """
 
     @object_dict_field(InterfaceType)
@@ -662,7 +664,7 @@ class ServiceTemplate(ExtensiblePresentation):
         This section contains an optional list of interface type definitions for use in the service
         template.
 
-        :rtype: dict of str, :class:`InterfaceType`
+        :type: {:obj:`basestring`: :class:`InterfaceType`}
         """
 
     @object_dict_field(RelationshipType)
@@ -672,7 +674,7 @@ class ServiceTemplate(ExtensiblePresentation):
         This section contains a set of relationship type definitions for use in the service
         template.
 
-        :rtype: dict of str, :class:`RelationshipType`
+        :type: {:obj:`basestring`: :class:`RelationshipType`}
         """
 
     @object_dict_field(NodeType)
@@ -681,7 +683,7 @@ class ServiceTemplate(ExtensiblePresentation):
         """
         This section contains a set of node type definitions for use in the service template.
 
-        :rtype: dict of str, :class:`NodeType`
+        :type: {:obj:`basestring`: :class:`NodeType`}
         """
 
     @object_dict_field(GroupType)
@@ -690,7 +692,7 @@ class ServiceTemplate(ExtensiblePresentation):
         """
         This section contains a list of group type definitions for use in the service template.
 
-        :rtype: dict of str, :class:`GroupType`
+        :type: {:obj:`basestring`: :class:`GroupType`}
         """
 
     @object_dict_field(PolicyType)
@@ -699,7 +701,7 @@ class ServiceTemplate(ExtensiblePresentation):
         """
         This section contains a list of policy type definitions for use in the service template.
 
-        :rtype: dict of str, :class:`PolicyType`
+        :type: {:obj:`basestring`: :class:`PolicyType`}
         """
 
     @object_field(TopologyTemplate)
@@ -709,7 +711,7 @@ class ServiceTemplate(ExtensiblePresentation):
         that represent the application's or service's components, as well as relationship templates
         representing relations between the components.
 
-        :rtype: :class:`TopologyTemplate`
+        :type: :class:`TopologyTemplate`
         """
 
     def _dump(self, context):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/types.py b/extensions/aria_extension_tosca/simple_v1_0/types.py
index d97b89c..570b89f 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/types.py
@@ -64,7 +64,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         An optional parent Artifact Type name the Artifact Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_getter(data_type_class_getter(Version))
@@ -73,7 +73,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         An optional version for the Artifact Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -81,7 +81,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         An optional description for the Artifact Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_field(str)
@@ -89,7 +89,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         The required mime type property for the Artifact Type.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_list_field(str)
@@ -97,7 +97,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         The required file extension property for the Artifact Type.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @object_dict_field(PropertyDefinition)
@@ -105,7 +105,7 @@ class ArtifactType(ExtensiblePresentation):
         """
         An optional list of property definitions for the Artifact Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @cachedmethod
@@ -147,7 +147,7 @@ class DataType(ExtensiblePresentation):
         """
         The optional key used when a datatype is derived from an existing TOSCA Data Type.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -155,7 +155,7 @@ class DataType(ExtensiblePresentation):
         """
         An optional version for the Data Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -163,7 +163,7 @@ class DataType(ExtensiblePresentation):
         """
         The optional description for the Data Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @field_validator(data_type_constraints_validator)
@@ -172,7 +172,7 @@ class DataType(ExtensiblePresentation):
         """
         The optional list of sequenced constraint clauses for the Data Type.
 
-        :rtype: list of (str, :class:`ConstraintClause`)
+        :type: list of (str, :class:`ConstraintClause`)
         """
 
     @field_validator(data_type_properties_validator)
@@ -182,7 +182,7 @@ class DataType(ExtensiblePresentation):
         The optional list property definitions that comprise the schema for a complex Data Type in
         TOSCA.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @cachedmethod
@@ -244,7 +244,7 @@ class CapabilityType(ExtensiblePresentation):
         """
         An optional parent capability type name this new Capability Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -252,7 +252,7 @@ class CapabilityType(ExtensiblePresentation):
         """
         An optional version for the Capability Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -260,7 +260,7 @@ class CapabilityType(ExtensiblePresentation):
         """
         An optional description for the Capability Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -270,7 +270,7 @@ class CapabilityType(ExtensiblePresentation):
 
         ARIA NOTE: The spec says 'list', but the examples are all of dicts.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_field(AttributeDefinition)
@@ -278,7 +278,7 @@ class CapabilityType(ExtensiblePresentation):
         """
         An optional list of attribute definitions for the Capability Type.
 
-        :rtype: dict of str, :class:`AttributeDefinition`
+        :type: {:obj:`basestring`: :class:`AttributeDefinition`}
         """
 
     @field_validator(list_type_validator('node type', convert_shorthand_to_full_type_name,
@@ -289,7 +289,7 @@ class CapabilityType(ExtensiblePresentation):
         An optional list of one or more valid names of Node Types that are supported as valid
         sources of any relationship established to the declared Capability Type.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @cachedmethod
@@ -345,7 +345,7 @@ class InterfaceType(ExtensiblePresentation):
         """
         An optional parent Interface Type name this new Interface Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -353,7 +353,7 @@ class InterfaceType(ExtensiblePresentation):
         """
         An optional version for the Interface Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -361,7 +361,7 @@ class InterfaceType(ExtensiblePresentation):
         """
         An optional description for the Interface Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -369,13 +369,13 @@ class InterfaceType(ExtensiblePresentation):
         """
         The optional list of input parameter definitions.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_unknown_fields(OperationDefinition)
     def operations(self):
         """
-        :rtype: dict of str, :class:`OperationDefinition`
+        :type: {:obj:`basestring`: :class:`OperationDefinition`}
         """
 
     @cachedmethod
@@ -424,7 +424,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional parent Relationship Type name the Relationship Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -432,7 +432,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional version for the Relationship Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -440,7 +440,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional description for the Relationship Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -448,7 +448,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional list of property definitions for the Relationship Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_field(AttributeDefinition)
@@ -456,7 +456,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional list of attribute definitions for the Relationship Type.
 
-        :rtype: dict of str, :class:`AttributeDefinition`
+        :type: {:obj:`basestring`: :class:`AttributeDefinition`}
         """
 
     @object_dict_field(InterfaceDefinition)
@@ -464,7 +464,7 @@ class RelationshipType(ExtensiblePresentation):
         """
         An optional list of interface definitions interfaces supported by the Relationship Type.
 
-        :rtype: dict of str, :class:`InterfaceDefinition`
+        :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
         """
 
     @field_validator(list_type_validator('capability type', convert_shorthand_to_full_type_name,
@@ -475,7 +475,7 @@ class RelationshipType(ExtensiblePresentation):
         An optional list of one or more names of Capability Types that are valid targets for this
         relationship.
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @cachedmethod
@@ -538,7 +538,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional parent Node Type name this new Node Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -546,7 +546,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional version for the Node Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -554,7 +554,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional description for the Node Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -562,7 +562,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional list of property definitions for the Node Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @object_dict_field(AttributeDefinition)
@@ -570,7 +570,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional list of attribute definitions for the Node Type.
 
-        :rtype: dict of str, :class:`AttributeDefinition`
+        :type: {:obj:`basestring`: :class:`AttributeDefinition`}
         """
 
     @object_sequenced_list_field(RequirementDefinition)
@@ -582,7 +582,7 @@ class NodeType(ExtensiblePresentation):
         more than one requirement of the same name, behavior is undefined. The idea is to use the
         "occurrences" field if you need to limit the number of requirement assignments.
 
-        :rtype: list of (str, :class:`RequirementDefinition`)
+        :type: list of (str, :class:`RequirementDefinition`)
         """
 
     @object_dict_field(CapabilityDefinition)
@@ -590,7 +590,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional list of capability definitions for the Node Type.
 
-        :rtype: list of :class:`CapabilityDefinition`
+        :type: list of :class:`CapabilityDefinition`
         """
 
     @object_dict_field(InterfaceDefinition)
@@ -598,7 +598,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional list of interface definitions supported by the Node Type.
 
-        :rtype: dict of str, :class:`InterfaceDefinition`
+        :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
         """
 
     @object_dict_field(ArtifactAssignment)
@@ -606,7 +606,7 @@ class NodeType(ExtensiblePresentation):
         """
         An optional list of named artifact definitions for the Node Type.
 
-        :rtype: dict of str, :class:`ArtifactAssignment`
+        :type: {:obj:`basestring`: :class:`ArtifactAssignment`}
         """
 
     @cachedmethod
@@ -694,7 +694,7 @@ class GroupType(ExtensiblePresentation):
         """
         An optional parent Group Type name the Group Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -702,7 +702,7 @@ class GroupType(ExtensiblePresentation):
         """
         An optional version for the Group Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -710,7 +710,7 @@ class GroupType(ExtensiblePresentation):
         """
         The optional description for the Group Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -718,7 +718,7 @@ class GroupType(ExtensiblePresentation):
         """
         An optional list of property definitions for the Group Type.
 
-        :rtype: dict of str, :class:`PropertyDefinition`
+        :type: {:obj:`basestring`: :class:`PropertyDefinition`}
         """
 
     @field_validator(list_type_validator('node type', convert_shorthand_to_full_type_name,
@@ -734,7 +734,7 @@ class GroupType(ExtensiblePresentation):
         For example, if we were to name this as an explicit Relationship Type we might call this
         "MemberOf" (group).
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @object_dict_field(InterfaceDefinition)
@@ -742,7 +742,7 @@ class GroupType(ExtensiblePresentation):
         """
         An optional list of interface definitions supported by the Group Type.
 
-        :rtype: dict of str, :class:`InterfaceDefinition`
+        :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
         """
 
     @cachedmethod
@@ -800,7 +800,7 @@ class PolicyType(ExtensiblePresentation):
         """
         An optional parent Policy Type name the Policy Type derives from.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Version)
@@ -808,7 +808,7 @@ class PolicyType(ExtensiblePresentation):
         """
         An optional version for the Policy Type definition.
 
-        :rtype: :class:`Version`
+        :type: :class:`Version`
         """
 
     @object_field(Description)
@@ -816,7 +816,7 @@ class PolicyType(ExtensiblePresentation):
         """
         The optional description for the Policy Type.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_dict_field(PropertyDefinition)
@@ -824,7 +824,7 @@ class PolicyType(ExtensiblePresentation):
         """
         An optional list of property definitions for the Policy Type.
 
-        :rtype: :class:`PropertyDefinition`
+        :type: :class:`PropertyDefinition`
         """
 
     @field_validator(list_node_type_or_group_type_validator)
@@ -838,7 +838,7 @@ class PolicyType(ExtensiblePresentation):
         were to name this as an explicit Relationship Type we might call this "AppliesTo" (node or
         group).
 
-        :rtype: list of str
+        :type: [:obj:`basestring`]
         """
 
     @cachedmethod

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/tests/orchestrator/workflows/core/test_events.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_events.py b/tests/orchestrator/workflows/core/test_events.py
index 30cc8ee..ff50eab 100644
--- a/tests/orchestrator/workflows/core/test_events.py
+++ b/tests/orchestrator/workflows/core/test_events.py
@@ -128,8 +128,8 @@ def run_standard_lifecycle_operation_on_node(ctx, op_name):
 
 
 def _assert_node_state_changed_as_a_result_of_standard_lifecycle_operation(node, op_name):
-    assert global_test_dict['transitional_state'] == NodeBase._op_to_state[op_name]['transitional']
-    assert node.state == NodeBase._op_to_state[op_name]['finished']
+    assert global_test_dict['transitional_state'] == NodeBase._OP_TO_STATE[op_name]['transitional']
+    assert node.state == NodeBase._OP_TO_STATE[op_name]['finished']
 
 
 @workflow


[10/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/__init__.py b/aria/parser/presentation/__init__.py
index a681695..5633e7b 100644
--- a/aria/parser/presentation/__init__.py
+++ b/aria/parser/presentation/__init__.py
@@ -13,6 +13,85 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Presentation package.
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.presentation.PresentationContext
+   aria.parser.presentation.PresenterException
+   aria.parser.presentation.PresenterNotFoundError
+   aria.parser.presentation.Field
+   aria.parser.presentation.NULL
+   aria.parser.presentation.none_to_null
+   aria.parser.presentation.null_to_none
+   aria.parser.presentation.Value
+   aria.parser.presentation.Presenter
+   aria.parser.presentation.PresenterSource
+   aria.parser.presentation.DefaultPresenterSource
+
+Presentations
+-------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.presentation.PresentationBase
+   aria.parser.presentation.Presentation
+   aria.parser.presentation.AsIsPresentation
+
+Field decorators
+----------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.presentation.has_fields
+   aria.parser.presentation.short_form_field
+   aria.parser.presentation.allow_unknown_fields
+   aria.parser.presentation.primitive_field
+   aria.parser.presentation.primitive_list_field
+   aria.parser.presentation.primitive_dict_field
+   aria.parser.presentation.primitive_dict_unknown_fields
+   aria.parser.presentation.object_field
+   aria.parser.presentation.object_list_field
+   aria.parser.presentation.object_dict_field
+   aria.parser.presentation.object_sequenced_list_field
+   aria.parser.presentation.object_dict_unknown_fields
+   aria.parser.presentation.field_getter
+   aria.parser.presentation.field_setter
+   aria.parser.presentation.field_validator
+
+Field validators
+----------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.presentation.type_validator
+   aria.parser.presentation.list_type_validator
+   aria.parser.presentation.list_length_validator
+   aria.parser.presentation.derived_from_validator
+
+Utilities
+---------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.presentation.get_locator
+   aria.parser.presentation.parse_types_dict_names
+   aria.parser.presentation.validate_primitive
+   aria.parser.presentation.validate_no_short_form
+   aria.parser.presentation.validate_no_unknown_fields
+   aria.parser.presentation.validate_known_fields
+   aria.parser.presentation.get_parent_presentation
+   aria.parser.presentation.report_issue_for_unknown_type
+   aria.parser.presentation.report_issue_for_parent_is_self
+   aria.parser.presentation.report_issue_for_unknown_parent_type
+   aria.parser.presentation.report_issue_for_circular_type_hierarchy
+"""
 
 from .exceptions import PresenterException, PresenterNotFoundError
 from .context import PresentationContext
@@ -29,8 +108,8 @@ from .field_validators import (type_validator, list_type_validator, list_length_
                                derived_from_validator)
 from .utils import (get_locator, parse_types_dict_names, validate_primitive, validate_no_short_form,
                     validate_no_unknown_fields, validate_known_fields, get_parent_presentation,
-                    report_issue_for_unknown_type, report_issue_for_parent_is_self,
-                    report_issue_for_circular_type_hierarchy)
+                    report_issue_for_unknown_type, report_issue_for_unknown_parent_type,
+                    report_issue_for_parent_is_self, report_issue_for_circular_type_hierarchy)
 
 __all__ = (
     'PresenterException',
@@ -74,5 +153,6 @@ __all__ = (
     'validate_known_fields',
     'get_parent_presentation',
     'report_issue_for_unknown_type',
+    'report_issue_for_unknown_parent_type',
     'report_issue_for_parent_is_self',
     'report_issue_for_circular_type_hierarchy')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/context.py b/aria/parser/presentation/context.py
index 26dcb39..44a6f82 100644
--- a/aria/parser/presentation/context.py
+++ b/aria/parser/presentation/context.py
@@ -19,16 +19,24 @@ from .source import DefaultPresenterSource
 
 class PresentationContext(object):
     """
-    Properties:
-
-    * :code:`presenter`: The generated presenter instance
-    * :code:`location`: From where we will generate the presenter
-    * :code:`presenter_source`: For finding presenter classes
-    * :code:`presenter_class`: Overrides :code:`presenter_source` with a specific class
-    * :code:`import_profile`: Whether to import the profile by default (defaults to true)
-    * :code:`threads`: Number of threads to use when reading data
-    * :code:`timeout`: Timeout in seconds for loading data
-    * :code:`print_exceptions`: Whether to print exceptions while reading data
+    Presentation context.
+
+    :ivar presenter: the generated presenter instance
+    :vartype presenter: ~aria.parser.presentation.Presenter
+    :ivar location: from where we will generate the presenter
+    :vartype location: ~aria.parser.loading.Location
+    :ivar presenter_source: for finding presenter classes
+    :vartype presenter_source: ~aria.parser.presentation.PresenterSource
+    :ivar presenter_class: overrides ``presenter_source`` with a specific class
+    :vartype presenter_class: type
+    :ivar import_profile: whether to import the profile by default (defaults to ``True``)
+    :vartype import_profile: bool
+    :ivar threads: number of threads to use when reading data
+    :vartype threads: int
+    :ivar timeout: timeout in seconds for loading data
+    :vartype timeout: float
+    :ivar print_exceptions: whether to print exceptions while reading data
+    :vartype print_exceptions: bool
     """
 
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/field_validators.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/field_validators.py b/aria/parser/presentation/field_validators.py
index 9903a1b..aa04913 100644
--- a/aria/parser/presentation/field_validators.py
+++ b/aria/parser/presentation/field_validators.py
@@ -25,9 +25,9 @@ def type_validator(type_name, *types_dict_names):
     Makes sure that the field refers to an existing type defined in the root presenter.
 
     The arguments from the second onwards are used to locate a nested field under
-    :code:`service_template` under the root presenter. The first of these can optionally
-    be a function, in which case it will be called to convert type names. This can be used
-    to support shorthand type names, aliases, etc.
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
 
     Can be used with the :func:`field_validator` decorator.
     """
@@ -58,9 +58,9 @@ def list_type_validator(type_name, *types_dict_names):
     Assumes that the field is a list.
 
     The arguments from the second onwards are used to locate a nested field under
-    :code:`service_template` under the root presenter. The first of these can optionally
-    be a function, in which case it will be called to convert type names. This can be used
-    to support shorthand type names, aliases, etc.
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
 
     Can be used with the :func:`field_validator` decorator.
     """
@@ -115,10 +115,9 @@ def derived_from_validator(*types_dict_names):
 
     Checks that we do not derive from ourselves and that we do not cause a circular hierarchy.
 
-    The arguments are used to locate a nested field under
-    :code:`service_template` under the root presenter.
-    The first of these can optionally be a function, in which case it will be called to convert type
-    names. This can be used to support shorthand type names, aliases, etc.
+    The arguments are used to locate a nested field under ``service_template`` under the root
+    presenter. The first of these can optionally be a function, in which case it will be called to
+    convert type names. This can be used to support shorthand type names, aliases, etc.
 
     Can be used with the :func:`field_validator` decorator.
     """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/fields.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/fields.py b/aria/parser/presentation/fields.py
index 7f85723..959bad1 100644
--- a/aria/parser/presentation/fields.py
+++ b/aria/parser/presentation/fields.py
@@ -39,19 +39,16 @@ def has_fields(cls):
     """
     Class decorator for validated field support.
 
-    1. Adds a :code:`FIELDS` class property that is a dict of all the fields.
-       Will inherit and merge :code:`FIELDS` properties from base classes if
-       they have them.
+    1. Adds a ``FIELDS`` class property that is a dict of all the fields. Will inherit and merge
+       ``FIELDS`` properties from base classes if they have them.
 
-    2. Generates automatic :code:`@property` implementations for the fields
-       with the help of a set of special function decorators.
+    2. Generates automatic ``@property`` implementations for the fields with the help of a set of
+       special function decorators.
 
-    The class also works with the Python dict protocol, so that
-    fields can be accessed via dict semantics. The functionality is
-    identical to that of using attribute access.
+    The class also works with the Python dict protocol, so that fields can be accessed via dict
+    semantics. The functionality is identical to that of using attribute access.
 
-    The class will also gain two utility methods, :code:`_iter_field_names`
-    and :code:`_iter_fields`.
+    The class will also gain two utility methods, ``_iter_field_names`` and ``_iter_fields``.
     """
 
     # Make sure we have FIELDS
@@ -267,8 +264,8 @@ def field_getter(getter_func):
     """
     Method decorator for overriding the getter function of a field.
 
-    The signature of the getter function must be: :code:`f(field, presentation, context)`.
-    The default getter can be accessed as :code:`field.default_get(presentation, context)`.
+    The signature of the getter function must be: ``f(field, presentation, context)``.
+    The default getter can be accessed as ```field.default_get(presentation, context)``.
 
     The function must already be decorated with a field decorator.
     """
@@ -286,8 +283,8 @@ def field_setter(setter_func):
     """
     Method decorator for overriding the setter function of a field.
 
-    The signature of the setter function must be: :code:`f(field, presentation, context, value)`.
-    The default setter can be accessed as :code:`field.default_set(presentation, context, value)`.
+    The signature of the setter function must be: ``f(field, presentation, context, value)``.
+    The default setter can be accessed as ``field.default_set(presentation, context, value)``.
 
     The function must already be decorated with a field decorator.
     """
@@ -305,8 +302,8 @@ def field_validator(validator_fn):
     """
     Method decorator for overriding the validator function of a field.
 
-    The signature of the validator function must be: :code:f(field, presentation, context)`.
-    The default validator can be accessed as :code:`field.default_validate(presentation, context)`.
+    The signature of the validator function must be: ``f(field, presentation, context)``.
+    The default validator can be accessed as ``field.default_validate(presentation, context)``.
 
     The function must already be decorated with a field decorator.
     """
@@ -373,7 +370,7 @@ def has_fields_contains(self, key):
 
 class Field(object):
     """
-    Field handler used by :code:`@has_fields` decorator.
+    Field handler used by ``@has_fields`` decorator.
     """
 
     def __init__(self, field_variant, func, cls=None, default=None, allowed=None, required=False):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/null.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/null.py b/aria/parser/presentation/null.py
index a018df4..287d2ba 100644
--- a/aria/parser/presentation/null.py
+++ b/aria/parser/presentation/null.py
@@ -33,7 +33,7 @@ NULL = Null()
 
 def none_to_null(value):
     """
-    Convert :code:`None` to :code:`NULL`, recursively.
+    Convert ``None`` to ``NULL``, recursively.
     """
 
     if value is None:
@@ -51,7 +51,7 @@ def none_to_null(value):
 
 def null_to_none(value):
     """
-    Convert :code:`NULL` to :code:`None`, recursively.
+    Convert ``NULL`` to ``None``, recursively.
     """
 
     if value is NULL:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/presentation.py b/aria/parser/presentation/presentation.py
index 644d880..7292562 100644
--- a/aria/parser/presentation/presentation.py
+++ b/aria/parser/presentation/presentation.py
@@ -52,18 +52,17 @@ class PresentationBase(HasCachedMethods):
 
     def _validate(self, context):
         """
-        Validates the presentation while reporting errors in the validation context but
-        *not* raising exceptions.
+        Validates the presentation while reporting errors in the validation context but *not*
+        raising exceptions.
 
-        The base class does not thing, but subclasses may override this for specialized
-        validation.
+        The base class does not thing, but subclasses may override this for specialized validation.
         """
 
     @property
     def _fullname(self):
         """
-        Always returns a usable full name of the presentation, whether it itself is named,
-        or recursing to its container, and finally defaulting to the class name.
+        Always returns a usable full name of the presentation, whether it itself is named, or
+        recursing to its container, and finally defaulting to the class name.
         """
 
         if self._name is not None:
@@ -75,10 +74,10 @@ class PresentationBase(HasCachedMethods):
     @property
     def _locator(self):
         """
-        Attempts to return the most relevant locator, whether we have one, or recursing
-        to our container.
+        Attempts to return the most relevant locator, whether we have one, or recursing to our
+        container.
 
-        :rtype: :class:`aria.reading.Locator`
+        :rtype: :class:`aria.parser.reading.Locator`
         """
 
         return get_locator(self._raw, self._container)
@@ -98,8 +97,8 @@ class PresentationBase(HasCachedMethods):
 
     def _get_from_dict(self, *names):
         """
-        Gets attributes recursively, except for the last name which is used
-        to get a value from the last dict.
+        Gets attributes recursively, except for the last name which is used to get a value from the
+        last dict.
         """
 
         if names:
@@ -110,10 +109,10 @@ class PresentationBase(HasCachedMethods):
 
     def _get_child_locator(self, *names):
         """
-        Attempts to return the locator of one our children. Will default to our locator
-        if not found.
+        Attempts to return the locator of one our children. Will default to our locator if not
+        found.
 
-        :rtype: :class:`aria.reading.Locator`
+        :rtype: :class:`aria.parser.reading.Locator`
         """
 
         if hasattr(self._raw, '_locator'):
@@ -126,9 +125,8 @@ class PresentationBase(HasCachedMethods):
         """
         Emits a colorized representation.
 
-        The base class will emit a sensible default representation of the fields,
-        (by calling :code:`_dump_content`), but subclasses may override this for specialized
-        dumping.
+        The base class will emit a sensible default representation of the fields, (by calling
+        ``_dump_content``), but subclasses may override this for specialized dumping.
         """
 
         if self._name:
@@ -142,8 +140,8 @@ class PresentationBase(HasCachedMethods):
         """
         Emits a colorized representation of the contents.
 
-        The base class will call :code:`_dump_field` on all the fields, but subclasses may
-        override this for specialized dumping.
+        The base class will call ``_dump_field`` on all the fields, but subclasses may override
+        this for specialized dumping.
         """
 
         if field_names:
@@ -159,8 +157,8 @@ class PresentationBase(HasCachedMethods):
         """
         Emits a colorized representation of the field.
 
-        According to the field type, this may trigger nested recursion. The nested
-        types will delegate to their :code:`_dump` methods.
+        According to the field type, this may trigger nested recursion. The nested types will
+        delegate to their ``_dump`` methods.
         """
 
         field = self.FIELDS[field_name]  # pylint: disable=no-member
@@ -179,16 +177,14 @@ class PresentationBase(HasCachedMethods):
 
 class Presentation(PresentationBase):
     """
-    Base class for ARIA presentations. A presentation is a Pythonic wrapper around
-    agnostic raw data, adding the ability to read and modify the data with proper
-    validation.
+    Base class for ARIA presentations. A presentation is a Pythonic wrapper around agnostic raw
+    data, adding the ability to read and modify the data with proper validation.
 
-    ARIA presentation classes will often be decorated with @has_fields, as that
-    mechanism automates a lot of field-specific validation. However, that is not a
-    requirement.
+    ARIA presentation classes will often be decorated with :func:`has_fields`, as that mechanism
+    automates a lot of field-specific validation. However, that is not a requirement.
 
-    Make sure that your utility property and method names begin with a "_", because
-    those names without a "_" prefix are normally reserved for fields.
+    Make sure that your utility property and method names begin with a ``_``, because those names
+    without a ``_`` prefix are normally reserved for fields.
     """
 
     def _validate(self, context):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/source.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/source.py b/aria/parser/presentation/source.py
index 7198b07..4bfb8e1 100644
--- a/aria/parser/presentation/source.py
+++ b/aria/parser/presentation/source.py
@@ -32,7 +32,7 @@ class PresenterSource(object):
 
 class DefaultPresenterSource(PresenterSource):
     """
-    The default ARIA presenter source supports TOSCA Simple Profile.
+    The default ARIA presenter source.
     """
 
     def __init__(self, classes=None):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/presentation/utils.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/utils.py b/aria/parser/presentation/utils.py
index fbe971b..f0fd390 100644
--- a/aria/parser/presentation/utils.py
+++ b/aria/parser/presentation/utils.py
@@ -25,7 +25,7 @@ def get_locator(*values):
     """
     Gets the first available locator.
 
-    :rtype: :class:`aria.reading.Locator`
+    :rtype: :class:`aria.parser.reading.Locator`
     """
 
     for v in values:
@@ -53,7 +53,7 @@ def validate_primitive(value, cls, coerce=False):
     Checks if the value is of the primitive type, optionally attempting to coerce it
     if it is not.
 
-    Raises a :code:`ValueError` if it isn't or if coercion failed.
+    :raises ValueError: if not a primitive type or if coercion failed.
     """
 
     if (cls is not None) and (value is not None) and (value is not NULL):
@@ -112,14 +112,14 @@ def validate_known_fields(context, presentation):
 
 def get_parent_presentation(context, presentation, *types_dict_names):
     """
-    Returns the parent presentation according to the :code:`derived_from` field, or None if invalid.
+    Returns the parent presentation according to the ``derived_from`` field, or ``None`` if invalid.
 
     Checks that we do not derive from ourselves and that we do not cause a circular hierarchy.
 
     The arguments from the third onwards are used to locate a nested field under
-    :code:`service_template` under the root presenter. The first of these can optionally
-    be a function, in which case it will be called to convert type names. This can be used
-    to support shorthand type names, aliases, etc.
+    ``service_template`` under the root presenter. The first of these can optionally be a function,
+    in which case it will be called to convert type names. This can be used to support shorthand
+    type names, aliases, etc.
     """
 
     type_name = presentation.derived_from

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/reading/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/__init__.py b/aria/parser/reading/__init__.py
index b5c0709..065ca56 100644
--- a/aria/parser/reading/__init__.py
+++ b/aria/parser/reading/__init__.py
@@ -10,6 +10,29 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Reading package.
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.reading.ReadingContext
+   ReaderException
+   ReaderNotFoundError
+   ReaderSyntaxError
+   AlreadyReadException
+   JinjaReader
+   JsonReader
+   Locator
+   deepcopy_with_locators
+   copy_locators
+   RawReader
+   Reader
+   ReaderSource
+   DefaultReaderSource
+   YamlReader
+"""
+
 from .raw import RawReader
 from .reader import Reader
 from .yaml import YamlReader

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/reading/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/context.py b/aria/parser/reading/context.py
index 02d4de9..233e407 100644
--- a/aria/parser/reading/context.py
+++ b/aria/parser/reading/context.py
@@ -16,10 +16,12 @@ from .source import DefaultReaderSource
 
 class ReadingContext(object):
     """
-    Properties:
+    Reading context.
 
-    * :code:`reader_source`: For finding reader instances
-    * :code:`reader`: Overrides :code:`reader_source` with a specific class
+    :ivar reader_source: for finding reader instances
+    :vartype reader_source: ReaderSource
+    :ivar reader: overrides ``reader_source`` with a specific class
+    :vartype reader: type
     """
 
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/reading/locator.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/locator.py b/aria/parser/reading/locator.py
index 4142ee7..965164d 100644
--- a/aria/parser/reading/locator.py
+++ b/aria/parser/reading/locator.py
@@ -124,7 +124,7 @@ class Locator(object):
 
 def deepcopy_with_locators(value):
     """
-    Like :code:`deepcopy`, but also copies over locators.
+    Like :func:`deepcopy`, but also copies over locators.
     """
 
     res = deepcopy(value)
@@ -134,7 +134,7 @@ def deepcopy_with_locators(value):
 
 def copy_locators(target, source):
     """
-    Copies over :code:`_locator` for all elements, recursively.
+    Copies over ``_locator`` for all elements, recursively.
 
     Assumes that target and source have exactly the same list/dict structure.
     """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/reading/reader.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/reader.py b/aria/parser/reading/reader.py
index fe64697..1a29f11 100644
--- a/aria/parser/reading/reader.py
+++ b/aria/parser/reading/reader.py
@@ -18,7 +18,7 @@ class Reader(object):
     """
     Base class for ARIA readers.
 
-    Readers provide agnostic raw data by consuming :class:`aria.loading.Loader` instances.
+    Readers provide agnostic raw data by consuming :class:`aria.parser.loading.Loader` instances.
     """
 
     def __init__(self, context, location, loader):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/specification.py
----------------------------------------------------------------------
diff --git a/aria/parser/specification.py b/aria/parser/specification.py
index 714bed1..4f452b8 100644
--- a/aria/parser/specification.py
+++ b/aria/parser/specification.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for cross-referencing code with specification documents.
+"""
+
 import re
 
 from ..extension import parser

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/validation/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/validation/__init__.py b/aria/parser/validation/__init__.py
index fead43b..21632ba 100644
--- a/aria/parser/validation/__init__.py
+++ b/aria/parser/validation/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Validation package.
+"""
+
 from .issue import Issue
 from .context import ValidationContext
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/validation/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/validation/context.py b/aria/parser/validation/context.py
index d81f1cd..ef641bd 100644
--- a/aria/parser/validation/context.py
+++ b/aria/parser/validation/context.py
@@ -23,13 +23,16 @@ from ...utils.formatting import as_raw
 
 class ValidationContext(object):
     """
-    Properties:
+    Validation context.
 
-    * :code:`allow_unknown_fields`: When False (the default) will report an issue
-            if an unknown field is used
-    * :code:`allow_primitive_coersion`: When False (the default) will not attempt to
-            coerce primitive field types
-    * :code:`max_level`: Maximum validation level to report (default is all)
+    :ivar allow_unknown_fields: when ``False`` (the default) will report an issue if an unknown
+     field is used
+    :vartype allow_unknown_fields: bool
+    :ivar allow_primitive_coersion`: when ``False`` (the default) will not attempt to coerce
+     primitive field types
+    :vartype allow_primitive_coersion: bool
+    :ivar max_level: maximum validation level to report (default is all)
+    :vartype max_level: int
     """
 
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/__init__.py
----------------------------------------------------------------------
diff --git a/aria/storage/__init__.py b/aria/storage/__init__.py
index bd7c8c1..a553ca7 100644
--- a/aria/storage/__init__.py
+++ b/aria/storage/__init__.py
@@ -14,29 +14,9 @@
 # limitations under the License.
 
 """
-ARIA's storage Sub-Package
-Path: aria.storage
-
-Storage package is a generic abstraction over different storage types.
-We define this abstraction with the following components:
-
-1. storage: simple mapi to use
-2. driver: implementation of the database client mapi.
-3. model: defines the structure of the table/document.
-4. field: defines a field/item in the model.
-
-API:
-    * application_storage_factory - function, default ARIA storage factory.
-    * Storage - class, simple storage mapi.
-    * models - module, default ARIA standard models.
-    * structures - module, default ARIA structures - holds the base model,
-                   and different fields types.
-    * Model - class, abstract model implementation.
-    * Field - class, base field implementation.
-    * IterField - class, base iterable field implementation.
-    * drivers - module, a pool of ARIA standard drivers.
-    * StorageDriver - class, abstract model implementation.
+Storage package.
 """
+
 from .core import (
     Storage,
     ModelStorage,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/api.py
----------------------------------------------------------------------
diff --git a/aria/storage/api.py b/aria/storage/api.py
index 3304721..a337743 100644
--- a/aria/storage/api.py
+++ b/aria/storage/api.py
@@ -12,15 +12,17 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-General storage API
+Storage APIs.
 """
+
 import threading
 
 
 class StorageAPI(object):
     """
-    General storage Base API
+    Base class for storage APIs.
     """
     def create(self, **kwargs):
         """
@@ -33,15 +35,12 @@ class StorageAPI(object):
 
 class ModelAPI(StorageAPI):
     """
-    A Base object for the model.
+    Base class for model APIs ("MAPI").
     """
     def __init__(self, model_cls, name=None, **kwargs):
         """
-        Base model API
-
-        :param model_cls: the representing class of the model
-        :param str name: the name of the model
-        :param kwargs:
+        :param model_cls: representing class of the model
+        :param name: name of the model
         """
         super(ModelAPI, self).__init__(**kwargs)
         self._model_cls = model_cls
@@ -59,46 +58,42 @@ class ModelAPI(StorageAPI):
     @property
     def name(self):
         """
-        The name of the class
-        :return: name of the class
+        Name of the class.
+
+        :type: :obj:`basestring`
         """
         return self._name
 
     @property
     def model_cls(self):
         """
-        The class represting the model
-        :return:
+        Class representing the model
+
+        :type: :obj:`Type`
         """
         return self._model_cls
 
     def get(self, entry_id, filters=None, **kwargs):
         """
-        Get entry from storage.
+        Gets a model from storage.
 
         :param entry_id:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract get method')
 
     def put(self, entry, **kwargs):
         """
-        Store entry in storage
+        Puts a model in storage.
 
         :param entry:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract store method')
 
     def delete(self, entry_id, **kwargs):
         """
-        Delete entry from storage.
+        Deletes a model from storage.
 
         :param entry_id:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract delete method')
 
@@ -107,32 +102,27 @@ class ModelAPI(StorageAPI):
 
     def iter(self, **kwargs):
         """
-        Iter over the entries in storage.
-
-        :param kwargs:
-        :return:
+        Iterate over all models in storage.
         """
         raise NotImplementedError('Subclass must implement abstract iter method')
 
     def update(self, entry, **kwargs):
         """
-        Update entry in storage.
+        Update a model in storage.
 
         :param entry:
         :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract update method')
 
 
 class ResourceAPI(StorageAPI):
     """
-    A Base object for the resource.
+    Base class for resource APIs ("RAPI").
     """
     def __init__(self, name, **kwargs):
         """
-        Base resource API
-        :param str name: the resource type
+        :param name: resource type
         """
         super(ResourceAPI, self).__init__(**kwargs)
         self._name = name
@@ -140,63 +130,57 @@ class ResourceAPI(StorageAPI):
     @property
     def name(self):
         """
-        The name of the resource
-        :return:
+        Name of resource.
+
+        :type: :obj:`basestring`
         """
         return self._name
 
     def read(self, entry_id, path, **kwargs):
         """
-        Get a bytesteam from the storage.
+        Get a bytesteam for a resource from storage.
 
         :param entry_id:
         :param path:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract read method')
 
     def delete(self, entry_id, path, **kwargs):
         """
-        Delete a resource from the storage.
+        Delete a resource from storage.
 
         :param entry_id:
         :param path:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract delete method')
 
     def download(self, entry_id, destination, path=None, **kwargs):
         """
-        Download a resource from the storage.
+        Download a resource from storage.
 
         :param entry_id:
         :param destination:
         :param path:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract download method')
 
     def upload(self, entry_id, source, path=None, **kwargs):
         """
-        Upload a resource to the storage.
+        Upload a resource to storage.
 
         :param entry_id:
         :param source:
         :param path:
-        :param kwargs:
-        :return:
         """
         raise NotImplementedError('Subclass must implement abstract upload method')
 
 
 def generate_lower_name(model_cls):
     """
-    Generates the name of the class from the class object. e.g. SomeClass -> some_class
-    :param model_cls: the class to evaluate.
-    :return: lower name
+    Generates the name of the class from the class object, e.g. ``SomeClass`` -> ``some_class``
+
+    :param model_cls: class to evaluate
+    :return: lowercase name
     :rtype: basestring
     """
     return getattr(model_cls, '__mapiname__', model_cls.__tablename__)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/collection_instrumentation.py
----------------------------------------------------------------------
diff --git a/aria/storage/collection_instrumentation.py b/aria/storage/collection_instrumentation.py
index 454f97a..c90cb18 100644
--- a/aria/storage/collection_instrumentation.py
+++ b/aria/storage/collection_instrumentation.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for instrumenting collections of models in storage.
+"""
+
 from . import exceptions
 
 
@@ -42,17 +46,15 @@ class _InstrumentedCollection(object):
         Instantiates the object from existing seq.
 
         :param seq: the original sequence to load from
-        :return:
         """
         raise NotImplementedError
 
     def _set(self, key, value):
         """
-        set the changes for the current object (not in the db)
+        Sets the changes for the current object (not in the database).
 
         :param key:
         :param value:
-        :return:
         """
         raise NotImplementedError
 
@@ -61,10 +63,10 @@ class _InstrumentedCollection(object):
 
     def _instrument(self, key, value):
         """
-        Instruments any collection to track changes (and ease of access)
+        Instruments any collection to track changes (and ease of access).
+
         :param key:
         :param value:
-        :return:
         """
         if isinstance(value, _InstrumentedCollection):
             return value
@@ -79,9 +81,9 @@ class _InstrumentedCollection(object):
 
     def _raw_value(self, value):
         """
-        Get the raw value.
+        Gets the raw value.
+
         :param value:
-        :return:
         """
         if isinstance(value, self._field_cls):
             return value.value
@@ -89,10 +91,10 @@ class _InstrumentedCollection(object):
 
     def _encapsulate_value(self, key, value):
         """
-        Create a new item cls if needed.
+        Creates a new item class if needed.
+
         :param key:
         :param value:
-        :return:
         """
         if isinstance(value, self._field_cls):
             return value
@@ -101,10 +103,10 @@ class _InstrumentedCollection(object):
 
     def __setitem__(self, key, value):
         """
-        Update the values in both the local and the db locations.
+        Updates the values in both the local and the database locations.
+
         :param key:
         :param value:
-        :return:
         """
         self._set(key, value)
         if self._is_top_level:
@@ -119,11 +121,11 @@ class _InstrumentedCollection(object):
 
     def _set_field(self, collection, key, value):
         """
-        enables updating the current change in the ancestors
-        :param collection: the collection to change
-        :param key: the key for the specific field
-        :param value: the new value
-        :return:
+        Enables updating the current change in the ancestors.
+
+        :param collection: collection to change
+        :param key: key for the specific field
+        :param value: new value
         """
         if isinstance(value, _InstrumentedCollection):
             value = value._raw
@@ -209,9 +211,10 @@ class _InstrumentedModel(_WrappedBase):
 
     def __init__(self, mapi, *args, **kwargs):
         """
-        The original model
-        :param wrapped: the model to be instrumented
-        :param mapi: the mapi for that model
+        The original model.
+
+        :param wrapped: model to be instrumented
+        :param mapi: MAPI for the wrapped model
         """
         super(_InstrumentedModel, self).__init__(*args, **kwargs)
         self._mapi = mapi
@@ -261,11 +264,10 @@ class _WrappedModel(_WrappedBase):
 
     def __init__(self, instrumentation_kwargs, *args, **kwargs):
         """
-
-        :param instrumented_cls: The class to be instrumented
-        :param instrumentation_cls: the instrumentation cls
-        :param wrapped: the currently wrapped instance
-        :param kwargs: and kwargs to the passed to the instrumented class.
+        :param instrumented_cls: class to be instrumented
+        :param instrumentation_cls: instrumentation cls
+        :param wrapped: currently wrapped instance
+        :param kwargs: passed to the instrumented class
         """
         super(_WrappedModel, self).__init__(*args, **kwargs)
         self._kwargs = instrumentation_kwargs

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/core.py
----------------------------------------------------------------------
diff --git a/aria/storage/core.py b/aria/storage/core.py
index 06c29e8..74b1147 100644
--- a/aria/storage/core.py
+++ b/aria/storage/core.py
@@ -14,29 +14,9 @@
 # limitations under the License.
 
 """
-ARIA's storage Sub-Package
-Path: aria.storage
-
-Storage package is a generic abstraction over different storage types.
-We define this abstraction with the following components:
-
-1. storage: simple mapi to use
-2. driver: implementation of the database client mapi.
-3. model: defines the structure of the table/document.
-4. field: defines a field/item in the model.
-
-API:
-    * application_storage_factory - function, default ARIA storage factory.
-    * Storage - class, simple storage mapi.
-    * models - module, default ARIA standard models.
-    * structures - module, default ARIA structures - holds the base model,
-                   and different fields types.
-    * Model - class, abstract model implementation.
-    * Field - class, base field implementation.
-    * IterField - class, base iterable field implementation.
-    * drivers - module, a pool of ARIA standard drivers.
-    * StorageDriver - class, abstract model implementation.
+Storage API management.
 """
+
 import copy
 from contextlib import contextmanager
 
@@ -52,7 +32,7 @@ __all__ = (
 
 class Storage(LoggerMixin):
     """
-    Represents the storage
+    Base class for storage managers.
     """
     def __init__(self,
                  api_cls,
@@ -62,13 +42,12 @@ class Storage(LoggerMixin):
                  initiator_kwargs=None,
                  **kwargs):
         """
-
-        :param api_cls: API cls for each model.
+        :param api_cls: API class for each entry
         :param api_kwargs:
-        :param items: the items to register
-        :param initiator: a func which initializes the storage before the first use.
-        This function should return a dict, this dict would be passed in addition to the api kwargs.
-        This enables the creation of any unpickable objects across process.
+        :param items: items to register
+        :param initiator: function which initializes the storage before the first use; this function
+         should return a dict, this dict would be passed in addition to the API kwargs; this enables
+         the creation of non-serializable objects
         :param initiator_kwargs:
         :param kwargs:
         """
@@ -112,22 +91,22 @@ class Storage(LoggerMixin):
 
     def register(self, entry):
         """
-        Register the entry to the storage
-        :param name:
-        :return:
+        Register an API.
+
+        :param entry:
         """
         raise NotImplementedError('Subclass must implement abstract register method')
 
 
 class ResourceStorage(Storage):
     """
-    Represents resource storage.
+    Manages storage resource APIs ("RAPIs").
     """
     def register(self, name):
         """
-        Register the resource type to resource storage.
-        :param name:
-        :return:
+        Register a storage resource API ("RAPI").
+
+        :param name: name
         """
         self.registered[name] = self.api(name=name, **self._all_api_kwargs)
         self.registered[name].create()
@@ -136,7 +115,7 @@ class ResourceStorage(Storage):
 
 class ModelStorage(Storage):
     """
-    Represents model storage.
+    Manages storage model APIs ("MAPIs").
     """
     def __init__(self, *args, **kwargs):
         if kwargs.get('initiator', None) is None:
@@ -145,9 +124,9 @@ class ModelStorage(Storage):
 
     def register(self, model_cls):
         """
-        Register the model into the model storage.
-        :param model_cls: the model to register.
-        :return:
+        Register a storage model API ("MAPI").
+
+        :param model_cls: model API to register
         """
         model_name = model_cls.__modelname__
         if model_name in self.registered:
@@ -162,8 +141,7 @@ class ModelStorage(Storage):
 
     def drop(self):
         """
-        Drop all the tables from the model.
-        :return:
+        Drop all the tables.
         """
         for mapi in self.registered.values():
             mapi.drop()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/storage/exceptions.py b/aria/storage/exceptions.py
index 3f0ecec..c538876 100644
--- a/aria/storage/exceptions.py
+++ b/aria/storage/exceptions.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-Storage based exceptions
+Storage exceptions.
 """
+
 from .. import exceptions
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/filesystem_rapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/filesystem_rapi.py b/aria/storage/filesystem_rapi.py
index 3ddc520..b425fa2 100644
--- a/aria/storage/filesystem_rapi.py
+++ b/aria/storage/filesystem_rapi.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-File system based RAPI
+File system implementation of the storage resource API ("RAPI").
 """
+
 import os
 import shutil
 from multiprocessing import RLock
@@ -30,13 +32,12 @@ from aria.storage import (
 
 class FileSystemResourceAPI(api.ResourceAPI):
     """
-    File system resource storage.
+    File system implementation of the storage resource API ("RAPI").
     """
 
     def __init__(self, directory, **kwargs):
         """
-        File system implementation for storage api.
-        :param str directory: root dir for storage.
+        :param directory: root dir for storage
         """
         super(FileSystemResourceAPI, self).__init__(**kwargs)
         self.directory = directory
@@ -47,8 +48,7 @@ class FileSystemResourceAPI(api.ResourceAPI):
     @contextmanager
     def connect(self):
         """
-        Established a connection and destroys it after use.
-        :return:
+        Establishes a connection and destroys it after use.
         """
         try:
             self._establish_connection()
@@ -60,16 +60,13 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def _establish_connection(self):
         """
-        Establish a conenction. used in the 'connect' contextmanager.
-        :return:
+        Establishes a connection. Used in the ``connect`` context manager.
         """
         self._lock.acquire()
 
-
     def _destroy_connection(self):
         """
-        Destroy a connection. used in the 'connect' contextmanager.
-        :return:
+        Destroys a connection. Used in the ``connect`` context manager.
         """
         self._lock.release()
 
@@ -79,9 +76,9 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def create(self, **kwargs):
         """
-        Create directory in storage by path.
-        tries to create the root directory as well.
-        :param str name: path of file in storage.
+        Creates a directory in by path. Tries to create the root directory as well.
+
+        :param name: path of directory
         """
         try:
             os.makedirs(self.directory)
@@ -94,11 +91,11 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def read(self, entry_id, path, **_):
         """
-        Retrieve the content of a file system storage resource.
+        Retrieves the contents of a file.
 
-        :param str entry_id: the id of the entry.
-        :param str path: a path to the specific resource to read.
-        :return: the content of the file.
+        :param entry_id: entry ID
+        :param path: path to resource
+        :return: contents of the file
         :rtype: bytes
         """
         resource_relative_path = os.path.join(self.name, entry_id, path or '')
@@ -118,11 +115,11 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def download(self, entry_id, destination, path=None, **_):
         """
-        Download a specific file or dir from the file system resource storage.
+        Downloads a file or directory.
 
-        :param str entry_id: the id of the entry.
-        :param str destination: the destination to download to
-        :param str path: the path to download relative to the root of the entry (otherwise all).
+        :param entry_id: entry ID
+        :param destination: download destination
+        :param path: path to download relative to the root of the entry (otherwise all)
         """
         resource_relative_path = os.path.join(self.name, entry_id, path or '')
         resource = os.path.join(self.directory, resource_relative_path)
@@ -136,10 +133,10 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def upload(self, entry_id, source, path=None, **_):
         """
-        Uploads a specific file or dir to the file system resource storage.
+        Uploads a file or directory.
 
-        :param str entry_id: the id of the entry.
-        :param source: the source of the files to upload.
+        :param entry_id: entry ID
+        :param source: source of the files to upload
         :param path: the destination of the file/s relative to the entry root dir.
         """
         resource_directory = os.path.join(self.directory, self.name, entry_id)
@@ -153,10 +150,10 @@ class FileSystemResourceAPI(api.ResourceAPI):
 
     def delete(self, entry_id, path=None, **_):
         """
-        Deletes a file system storage resource.
+        Deletes a file or directory.
 
-        :param str entry_id: the id of the entry.
-        :param str path: a path to delete relative to the root of the entry (otherwise all).
+        :param entry_id: entry ID
+        :param path: path to delete relative to the root of the entry (otherwise all)
         """
         destination = os.path.join(self.directory, self.name, entry_id, path or '')
         if os.path.exists(destination):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/storage/sql_mapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/sql_mapi.py b/aria/storage/sql_mapi.py
index bb6223a..975ada7 100644
--- a/aria/storage/sql_mapi.py
+++ b/aria/storage/sql_mapi.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-SQLAlchemy based MAPI
+SQLAlchemy implementation of the storage model API ("MAPI").
 """
+
 import os
 import platform
 
@@ -42,7 +44,7 @@ _predicates = {'ge': '__ge__',
 
 class SQLAlchemyModelAPI(api.ModelAPI):
     """
-    SQL based MAPI.
+    SQLAlchemy implementation of the storage model API ("MAPI").
     """
 
     def __init__(self,
@@ -54,7 +56,8 @@ class SQLAlchemyModelAPI(api.ModelAPI):
         self._session = session
 
     def get(self, entry_id, include=None, **kwargs):
-        """Return a single result based on the model class and element ID
+        """
+        Returns a single result based on the model class and element ID
         """
         query = self._get_query(include, {'id': entry_id})
         result = query.first()
@@ -102,25 +105,28 @@ class SQLAlchemyModelAPI(api.ModelAPI):
              filters=None,
              sort=None,
              **kwargs):
-        """Return a (possibly empty) list of `model_class` results
+        """
+        Returns a (possibly empty) list of ``model_class`` results.
         """
         for result in self._get_query(include, filters, sort):
             yield self._instrument(result)
 
     def put(self, entry, **kwargs):
-        """Create a `model_class` instance from a serializable `model` object
+        """
+        Creatse a ``model_class`` instance from a serializable ``model`` object.
 
-        :param entry: A dict with relevant kwargs, or an instance of a class
-        that has a `to_dict` method, and whose attributes match the columns
-        of `model_class` (might also my just an instance of `model_class`)
-        :return: An instance of `model_class`
+        :param entry: dict with relevant kwargs, or an instance of a class that has a ``to_dict``
+         method, and whose attributes match the columns of ``model_class`` (might also be just an
+         instance of ``model_class``)
+        :return: an instance of ``model_class``
         """
         self._session.add(entry)
         self._safe_commit()
         return entry
 
     def delete(self, entry, **kwargs):
-        """Delete a single result based on the model class and element ID
+        """
+        Deletes a single result based on the model class and element ID.
         """
         self._load_relationships(entry)
         self._session.delete(entry)
@@ -128,17 +134,19 @@ class SQLAlchemyModelAPI(api.ModelAPI):
         return entry
 
     def update(self, entry, **kwargs):
-        """Add `instance` to the DB session, and attempt to commit
+        """
+        Adds ``instance`` to the database session, and attempts to commit.
 
-        :return: The updated instance
+        :return: updated instance
         """
         return self.put(entry)
 
     def refresh(self, entry):
-        """Reload the instance with fresh information from the DB
+        """
+        Reloads the instance with fresh information from the database.
 
-        :param entry: Instance to be re-loaded from the DB
-        :return: The refreshed instance
+        :param entry: instance to be re-loaded from the database
+        :return: refreshed instance
         """
         self._session.refresh(entry)
         self._load_relationships(entry)
@@ -160,14 +168,14 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     def drop(self):
         """
-        Drop the table from the storage.
-        :return:
+        Drops the table.
         """
         self.model_cls.__table__.drop(self._engine)
 
     def _safe_commit(self):
-        """Try to commit changes in the session. Roll back if exception raised
-        Excepts SQLAlchemy errors and rollbacks if they're caught
+        """
+        Try to commit changes in the session. Roll back if exception raised SQLAlchemy errors and
+        rolls back if they're caught.
         """
         try:
             self._session.commit()
@@ -179,11 +187,11 @@ class SQLAlchemyModelAPI(api.ModelAPI):
             raise exceptions.StorageError('SQL Storage error: {0}'.format(str(e)))
 
     def _get_base_query(self, include, joins):
-        """Create the initial query from the model class and included columns
+        """
+        Create the initial query from the model class and included columns.
 
-        :param include: A (possibly empty) list of columns to include in
-        the query
-        :return: An SQLAlchemy AppenderQuery object
+        :param include: (possibly empty) list of columns to include in the query
+        :return: SQLAlchemy AppenderQuery object
         """
         # If only some columns are included, query through the session object
         if include:
@@ -199,9 +207,10 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     @staticmethod
     def _get_joins(model_class, columns):
-        """Get a list of all the tables on which we need to join
+        """
+        Gets a list of all the tables on which we need to join.
 
-        :param columns: A set of all attributes involved in the query
+        :param columns: set of all attributes involved in the query
         """
 
         # Using a list instead of a set because order is important
@@ -222,12 +231,13 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     @staticmethod
     def _sort_query(query, sort=None):
-        """Add sorting clauses to the query
+        """
+        Adds sorting clauses to the query.
 
-        :param query: Base SQL query
-        :param sort: An optional dictionary where keys are column names to
-        sort by, and values are the order (asc/desc)
-        :return: An SQLAlchemy AppenderQuery object
+        :param query: base SQL query
+        :param sort: optional dictionary where keys are column names to sort by, and values are
+         the order (asc/desc)
+        :return: SQLAlchemy AppenderQuery object
         """
         if sort:
             for column, order in sort.items():
@@ -237,13 +247,13 @@ class SQLAlchemyModelAPI(api.ModelAPI):
         return query
 
     def _filter_query(self, query, filters):
-        """Add filter clauses to the query
+        """
+        Adds filter clauses to the query.
 
-        :param query: Base SQL query
-        :param filters: An optional dictionary where keys are column names to
-        filter by, and values are values applicable for those columns (or lists
-        of such values)
-        :return: An SQLAlchemy AppenderQuery object
+        :param query: base SQL query
+        :param filters: optional dictionary where keys are column names to filter by, and values
+         are values applicable for those columns (or lists of such values)
+        :return: SQLAlchemy AppenderQuery object
         """
         return self._add_value_filter(query, filters)
 
@@ -264,17 +274,16 @@ class SQLAlchemyModelAPI(api.ModelAPI):
                    include=None,
                    filters=None,
                    sort=None):
-        """Get an SQL query object based on the params passed
-
-        :param model_class: SQL DB table class
-        :param include: An optional list of columns to include in the query
-        :param filters: An optional dictionary where keys are column names to
-        filter by, and values are values applicable for those columns (or lists
-        of such values)
-        :param sort: An optional dictionary where keys are column names to
-        sort by, and values are the order (asc/desc)
-        :return: A sorted and filtered query with only the relevant
-        columns
+        """
+        Gets a SQL query object based on the params passed.
+
+        :param model_class: SQL database table class
+        :param include: optional list of columns to include in the query
+        :param filters: optional dictionary where keys are column names to filter by, and values
+         are values applicable for those columns (or lists of such values)
+        :param sort: optional dictionary where keys are column names to sort by, and values are the
+         order (asc/desc)
+        :return: sorted and filtered query with only the relevant columns
         """
         include, filters, sort, joins = self._get_joins_and_converted_columns(
             include, filters, sort
@@ -305,9 +314,10 @@ class SQLAlchemyModelAPI(api.ModelAPI):
                                          include,
                                          filters,
                                          sort):
-        """Get a list of tables on which we need to join and the converted
-        `include`, `filters` and `sort` arguments (converted to actual SQLA
-        column/label objects instead of column names)
+        """
+        Gets a list of tables on which we need to join and the converted ``include``, ``filters``
+        and ```sort`` arguments (converted to actual SQLAlchemy column/label objects instead of
+        column names).
         """
         include = include or []
         filters = filters or dict()
@@ -325,8 +335,9 @@ class SQLAlchemyModelAPI(api.ModelAPI):
                                       include,
                                       filters,
                                       sort):
-        """Go over the optional parameters (include, filters, sort), and
-        replace column names with actual SQLA column objects
+        """
+        Gooes over the optional parameters (include, filters, sort), and replace column names with
+        actual SQLAlechmy column objects.
         """
         include = [self._get_column(c) for c in include]
         filters = dict((self._get_column(c), filters[c]) for c in filters)
@@ -335,9 +346,10 @@ class SQLAlchemyModelAPI(api.ModelAPI):
         return include, filters, sort
 
     def _get_column(self, column_name):
-        """Return the column on which an action (filtering, sorting, etc.)
-        would need to be performed. Can be either an attribute of the class,
-        or an association proxy linked to a relationship the class has
+        """
+        Returns the column on which an action (filtering, sorting, etc.) would need to be performed.
+        Can be either an attribute of the class, or an association proxy linked to a relationship
+        in the class.
         """
         column = getattr(self.model_cls, column_name)
         if column.is_attribute:
@@ -352,15 +364,16 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     @staticmethod
     def _paginate(query, pagination):
-        """Paginate the query by size and offset
-
-        :param query: Current SQLAlchemy query object
-        :param pagination: An optional dict with size and offset keys
-        :return: A tuple with four elements:
-        - res ults: `size` items starting from `offset`
-        - the total count of items
-        - `size` [default: 0]
-        - `offset` [default: 0]
+        """
+        Paginates the query by size and offset.
+
+        :param query: current SQLAlchemy query object
+        :param pagination: optional dict with size and offset keys
+        :return: tuple with four elements:
+         * results: ``size`` items starting from ``offset``
+         * the total count of items
+         * ``size`` [default: 0]
+         * ``offset`` [default: 0]
         """
         if pagination:
             size = pagination.get('size', 0)
@@ -374,8 +387,9 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     @staticmethod
     def _load_relationships(instance):
-        """A helper method used to overcome a problem where the relationships
-        that rely on joins aren't being loaded automatically
+        """
+        Helper method used to overcome a problem where the relationships that rely on joins aren't
+        being loaded automatically.
         """
         for rel in instance.__mapper__.relationships:
             getattr(instance, rel.key)
@@ -389,13 +403,15 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
 def init_storage(base_dir, filename='db.sqlite'):
     """
-    A builtin ModelStorage initiator.
-    Creates a sqlalchemy engine and a session to be passed to the mapi.
+    Built-in ModelStorage initiator.
+
+    Creates a SQLAlchemy engine and a session to be passed to the MAPI.
+
+    ``initiator_kwargs`` must be passed to the ModelStorage which must hold the ``base_dir`` for the
+    location of the database file, and an option filename. This would create an SQLite database.
 
-    Initiator_kwargs must be passed to the ModelStorage which must hold the base_dir for the
-    location of the db file, and an option filename. This would create an sqlite db.
-    :param base_dir: the dir of the db
-    :param filename: the db file name.
+    :param base_dir: directory of the database
+    :param filename: database file name.
     :return:
     """
     uri = 'sqlite:///{platform_char}{path}'.format(
@@ -415,7 +431,7 @@ def init_storage(base_dir, filename='db.sqlite'):
 
 class ListResult(list):
     """
-    a ListResult contains results about the requested items.
+    Contains results about the requested items.
     """
     def __init__(self, metadata, *args, **qwargs):
         super(ListResult, self).__init__(*args, **qwargs)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/__init__.py
----------------------------------------------------------------------
diff --git a/aria/utils/__init__.py b/aria/utils/__init__.py
index ae1e83e..2a957a9 100644
--- a/aria/utils/__init__.py
+++ b/aria/utils/__init__.py
@@ -12,3 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+General-purpose utilities package.
+"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/archive.py
----------------------------------------------------------------------
diff --git a/aria/utils/archive.py b/aria/utils/archive.py
index 63d9004..29efcb1 100644
--- a/aria/utils/archive.py
+++ b/aria/utils/archive.py
@@ -10,6 +10,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Archive utilities.
+"""
 
 import os
 import tarfile

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/argparse.py
----------------------------------------------------------------------
diff --git a/aria/utils/argparse.py b/aria/utils/argparse.py
index 365c148..a05a841 100644
--- a/aria/utils/argparse.py
+++ b/aria/utils/argparse.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Enhancements to Python's ``argparse`` module.
+"""
+
 from __future__ import absolute_import  # so we can import standard 'argparse'
 
 from argparse import ArgumentParser as BaseArgumentParser
@@ -27,7 +31,7 @@ class ArgumentParser(BaseArgumentParser):
 
     def add_flag_argument(self, name, help_true=None, help_false=None, default=False):
         """
-        Adds a flag argument as two arguments: :code:`--my-flag` and :code:`--no-my-flag`.
+        Adds a flag argument as two arguments: ``--my-flag`` and ``--no-my-flag``.
         """
 
         dest = name.replace('-', '_')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/caching.py
----------------------------------------------------------------------
diff --git a/aria/utils/caching.py b/aria/utils/caching.py
index c9e475a..5f8cd88 100644
--- a/aria/utils/caching.py
+++ b/aria/utils/caching.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Caching utilities.
+"""
+
 from __future__ import absolute_import  # so we can import standard 'collections' and 'threading'
 
 from threading import Lock
@@ -27,8 +31,8 @@ class cachedmethod(object):  # pylint: disable=invalid-name
 
     The implementation is thread-safe.
 
-    Supports :code:`cache_info` to be compatible with Python 3's :code:`functools.lru_cache`.
-    Note that the statistics are combined for all instances of the class.
+    Supports ``cache_info`` to be compatible with Python 3's ``functools.lru_cache``. Note that the
+    statistics are combined for all instances of the class.
 
     Won't use the cache if not called when bound to an object, allowing you to override the cache.
 
@@ -39,6 +43,7 @@ class cachedmethod(object):  # pylint: disable=invalid-name
     ENABLED = True
 
     def __init__(self, func):
+        self.__doc__ = func.__doc__
         self.func = func
         self.hits = 0
         self.misses = 0

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/collections.py
----------------------------------------------------------------------
diff --git a/aria/utils/collections.py b/aria/utils/collections.py
index 1e732aa..ccc37a1 100644
--- a/aria/utils/collections.py
+++ b/aria/utils/collections.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Additional collection classes and collection utilities.
+"""
+
 from __future__ import absolute_import  # so we can import standard 'collections'
 
 from copy import deepcopy
@@ -32,8 +36,8 @@ class FrozenList(list):
     """
     An immutable list.
 
-    After initialization it will raise :class:`TypeError` exceptions if modification
-    is attempted.
+    After initialization it will raise :class:`~exceptions.TypeError` exceptions if modification is
+    attempted.
 
     Note that objects stored in the list may not be immutable.
     """
@@ -78,12 +82,13 @@ class FrozenList(list):
 
 EMPTY_READ_ONLY_LIST = FrozenList()
 
+
 class FrozenDict(OrderedDict):
     """
     An immutable ordered dict.
 
-    After initialization it will raise :class:`TypeError` exceptions if modification
-    is attempted.
+    After initialization it will raise :class:`~exceptions.TypeError` exceptions if modification is
+    attempted.
 
     Note that objects stored in the dict may not be immutable.
     """
@@ -109,9 +114,11 @@ class FrozenDict(OrderedDict):
 
 EMPTY_READ_ONLY_DICT = FrozenDict()
 
+
 class StrictList(list):
     """
-    A list that raises :class:`TypeError` exceptions when objects of the wrong type are inserted.
+    A list that raises :class:`~exceptions.TypeError` exceptions when objects of the wrong type are
+    inserted.
     """
 
     def __init__(self,
@@ -168,10 +175,11 @@ class StrictList(list):
         value = self._wrap(value)
         return super(StrictList, self).insert(index, value)
 
+
 class StrictDict(OrderedDict):
     """
-    An ordered dict that raises :class:`TypeError` exceptions
-    when keys or values of the wrong type are used.
+    An ordered dict that raises :class:`~exceptions.TypeError` exceptions when keys or values of the
+    wrong type are used.
     """
 
     def __init__(self,
@@ -211,6 +219,7 @@ class StrictDict(OrderedDict):
             value = self.wrapper_function(value)
         return super(StrictDict, self).__setitem__(key, value)
 
+
 def merge(dict_a, dict_b, path=None, strict=False):
     """
     Merges dicts, recursively.
@@ -234,12 +243,14 @@ def merge(dict_a, dict_b, path=None, strict=False):
             dict_a[key] = value_b
     return dict_a
 
+
 def is_removable(_container, _key, v):
     return (v is None) or ((isinstance(v, dict) or isinstance(v, list)) and (len(v) == 0))
 
+
 def prune(value, is_removable_function=is_removable):
     """
-    Deletes :code:`None` and empty lists and dicts, recursively.
+    Deletes ``None`` and empty lists and dicts, recursively.
     """
 
     if isinstance(value, list):
@@ -258,10 +269,11 @@ def prune(value, is_removable_function=is_removable):
     return value
 
 
-# TODO (left for tal): Move following two methods to some place parser specific
+# TODO: Move following two methods to some place parser specific
+
 def deepcopy_with_locators(value):
     """
-    Like :code:`deepcopy`, but also copies over locators.
+    Like :func:`~copy.deepcopy`, but also copies over locators.
     """
 
     res = deepcopy(value)
@@ -271,7 +283,7 @@ def deepcopy_with_locators(value):
 
 def copy_locators(target, source):
     """
-    Copies over :code:`_locator` for all elements, recursively.
+    Copies over ``_locator`` for all elements, recursively.
 
     Assumes that target and source have exactly the same list/dict structure.
     """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/console.py
----------------------------------------------------------------------
diff --git a/aria/utils/console.py b/aria/utils/console.py
index 55d2529..642cbb1 100644
--- a/aria/utils/console.py
+++ b/aria/utils/console.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Abstraction API above terminal color libraries.
+"""
+
 from clint.textui.core import STDOUT
 from clint.textui import puts as _puts
 from clint.textui.colored import ColoredString as _ColoredString

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/utils/exceptions.py b/aria/utils/exceptions.py
index b60cee4..5bb0e6d 100644
--- a/aria/utils/exceptions.py
+++ b/aria/utils/exceptions.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for extracting and formatting Python exceptions.
+"""
+
 import sys
 import linecache
 import StringIO

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/file.py
----------------------------------------------------------------------
diff --git a/aria/utils/file.py b/aria/utils/file.py
index 6d1aa16..75f2859 100644
--- a/aria/utils/file.py
+++ b/aria/utils/file.py
@@ -13,13 +13,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+File utilities.
+"""
+
 import errno
 import os
 import shutil
 
 
 def makedirs(path):
-    """An extension of os.makedirs that doesn't fail if the directory already exists"""
+    """
+    Enhancement of :func:`os.makedirs` that doesn't fail if the directory already exists.
+    """
     if os.path.isdir(path):
         return
     try:
@@ -29,7 +35,6 @@ def makedirs(path):
             raise
 
 def remove_if_exists(path):
-
     try:
         if os.path.isfile(path):
             os.remove(path)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/formatting.py
----------------------------------------------------------------------
diff --git a/aria/utils/formatting.py b/aria/utils/formatting.py
index b8d24cd..fa34b7d 100644
--- a/aria/utils/formatting.py
+++ b/aria/utils/formatting.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+String formatting and string-based format utilities.
+"""
+
 import json
 from types import MethodType
 
@@ -42,8 +46,7 @@ yaml.representer.RoundTripRepresenter.add_representer(
 
 class JsonAsRawEncoder(json.JSONEncoder):
     """
-    A :class:`JSONEncoder` that will use the :code:`as_raw` property of objects
-    if available.
+    A :class:`JSONEncoder` that will use the ``as_raw`` property of objects if available.
     """
     def raw_encoder_default(self, obj):
         try:
@@ -61,8 +64,7 @@ class JsonAsRawEncoder(json.JSONEncoder):
 
 class YamlAsRawDumper(yaml.dumper.RoundTripDumper):  # pylint: disable=too-many-ancestors
     """
-    A :class:`RoundTripDumper` that will use the :code:`as_raw` property of objects
-    if available.
+    A :class:`RoundTripDumper` that will use the ``as_raw`` property of objects if available.
     """
 
     def represent_data(self, data):
@@ -101,8 +103,8 @@ def decode_dict(data):
 
 def safe_str(value):
     """
-    Like :code:`str` coercion, but makes sure that Unicode strings are properly
-    encoded, and will never return None.
+    Like :class:`str` coercion, but makes sure that Unicode strings are properly encoded, and will
+    never return ``None``.
     """
 
     try:
@@ -113,7 +115,7 @@ def safe_str(value):
 
 def safe_repr(value):
     """
-    Like :code:`repr`, but calls :code:`as_raw` and :code:`as_agnostic` first.
+    Like :func:`repr`, but calls :func:`as_raw` and :func:`as_agnostic` first.
     """
 
     return repr(as_agnostic(as_raw(value)))
@@ -143,7 +145,7 @@ def pluralize(noun):
 
 def as_raw(value):
     """
-    Converts values using their :code:`as_raw` property, if it exists, recursively.
+    Converts values using their ``as_raw`` property, if it exists, recursively.
     """
 
     if hasattr(value, 'as_raw'):
@@ -164,7 +166,7 @@ def as_raw(value):
 
 def as_raw_list(value):
     """
-    Assuming value is a list, converts its values using :code:`as_raw`.
+    Assuming value is a list, converts its values using :func:`as_raw`.
     """
 
     if value is None:
@@ -176,8 +178,7 @@ def as_raw_list(value):
 
 def as_raw_dict(value):
     """
-    Assuming value is a dict, converts its values using :code:`as_raw`.
-    The keys are left as is.
+    Assuming value is a dict, converts its values using :func:`as_raw`. The keys are left as is.
     """
 
     if value is None:
@@ -188,8 +189,8 @@ def as_raw_dict(value):
 
 def as_agnostic(value):
     """
-    Converts subclasses of list and dict to standard lists and dicts, and Unicode strings
-    to non-Unicode if possible, recursively.
+    Converts subclasses of list and dict to standard lists and dicts, and Unicode strings to
+    non-Unicode if possible, recursively.
 
     Useful for creating human-readable output of structures.
     """
@@ -216,8 +217,7 @@ def as_agnostic(value):
 
 def json_dumps(value, indent=2):
     """
-    JSON dumps that supports Unicode and the :code:`as_raw` property of objects
-    if available.
+    JSON dumps that supports Unicode and the ``as_raw`` property of objects if available.
     """
 
     return json.dumps(value, indent=indent, ensure_ascii=False, cls=JsonAsRawEncoder)
@@ -225,8 +225,7 @@ def json_dumps(value, indent=2):
 
 def yaml_dumps(value, indent=2):
     """
-    YAML dumps that supports Unicode and the :code:`as_raw` property of objects
-    if available.
+    YAML dumps that supports Unicode and the ``as_raw`` property of objects if available.
     """
 
     return yaml.dump(value, indent=indent, allow_unicode=True, Dumper=YamlAsRawDumper)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/http.py
----------------------------------------------------------------------
diff --git a/aria/utils/http.py b/aria/utils/http.py
index 7bdfd79..c8357e9 100644
--- a/aria/utils/http.py
+++ b/aria/utils/http.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+HTTP utilities.
+"""
+
 import os
 import tempfile
 
@@ -20,17 +24,17 @@ import requests
 
 
 def download_file(url, destination=None, logger=None, progress_handler=None):
-    """Download file.
-
-    May raise IOError as well as requests.exceptions.RequestException
-    :param url: Location of the file to download
-    :type url: str
-    :param destination:
-        Location where the file should be saved (autogenerated by default)
-    :type destination: str | None
-    :returns: Location where the file was saved
-    :rtype: str
+    """
+    Download file.
 
+    :param url: URL from which to download
+    :type url: basestring
+    :param destination: path where the file should be saved or ``None`` to auto-generate
+    :type destination: basestring
+    :returns: path where the file was saved
+    :rtype: basestring
+    :raises exceptions.IOError:
+    :raises requests.exceptions.RequestException:
     """
     chunk_size = 1024
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/imports.py
----------------------------------------------------------------------
diff --git a/aria/utils/imports.py b/aria/utils/imports.py
index 35aa0fc..14ad09e 100644
--- a/aria/utils/imports.py
+++ b/aria/utils/imports.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Utility methods for dynamically loading python code
+Utilities for dynamically loading Python code.
 """
 
 import pkgutil
@@ -50,8 +50,8 @@ def import_fullname(name, paths=None):
 
 def import_modules(name):
     """
-    Imports a module and all its sub-modules, recursively.
-    Relies on modules defining a 'MODULES' attribute listing their sub-module names.
+    Imports a module and all its sub-modules, recursively. Relies on modules defining a ``MODULES``
+    attribute listing their sub-module names.
     """
 
     module = __import__(name, fromlist=['MODULES'], level=0)
@@ -63,9 +63,9 @@ def import_modules(name):
 # TODO merge with import_fullname
 def load_attribute(attribute_path):
     """
-    Dynamically load an attribute based on the path to it.
-    e.g. some_package.some_module.some_attribute, will load the some_attribute from the
-    some_package.some_module module
+    Dynamically load an attribute based on the path to it. E.g.
+    ``some_package.some_module.some_attribute``, will load ``some_attribute`` from the
+    ``some_package.some_module`` module.
     """
     module_name, attribute_name = attribute_path.rsplit('.', 1)
     try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/openclose.py
----------------------------------------------------------------------
diff --git a/aria/utils/openclose.py b/aria/utils/openclose.py
index 19740eb..722885c 100644
--- a/aria/utils/openclose.py
+++ b/aria/utils/openclose.py
@@ -13,9 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for working with open/close patterns.
+"""
+
 class OpenClose(object):
     """
-    Wraps an object that has open() and close() methods to support the "with" keyword.
+    Wraps an object that has ``open()`` and ``close()`` methods to support the ``with`` keyword.
     """
 
     def __init__(self, wrapped):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/plugin.py
----------------------------------------------------------------------
diff --git a/aria/utils/plugin.py b/aria/utils/plugin.py
index b7f94a1..4fb6a8e 100644
--- a/aria/utils/plugin.py
+++ b/aria/utils/plugin.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Plugin utilities.
+"""
+
 import wagon
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/process.py
----------------------------------------------------------------------
diff --git a/aria/utils/process.py b/aria/utils/process.py
index 9aeae67..ec4a72d 100644
--- a/aria/utils/process.py
+++ b/aria/utils/process.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Process utilities.
+"""
+
 import os
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/specification.py
----------------------------------------------------------------------
diff --git a/aria/utils/specification.py b/aria/utils/specification.py
index e74c103..8c51134 100644
--- a/aria/utils/specification.py
+++ b/aria/utils/specification.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for cross-referencing code with specification documents.
+"""
+
 from .collections import OrderedDict
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/threading.py
----------------------------------------------------------------------
diff --git a/aria/utils/threading.py b/aria/utils/threading.py
index bfd30f5..b9d627a 100644
--- a/aria/utils/threading.py
+++ b/aria/utils/threading.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Threading utilities.
+"""
+
 from __future__ import absolute_import  # so we can import standard 'threading'
 
 import sys
@@ -26,6 +30,7 @@ from .exceptions import print_exception
 class ExecutorException(Exception):
     pass
 
+
 class DaemonThread(Thread):
     def __init__(self, *args, **kwargs):
         super(DaemonThread, self).__init__(*args, **kwargs)
@@ -33,16 +38,15 @@ class DaemonThread(Thread):
 
     def run(self):
         """
-        We're overriding `Thread.run` in order to avoid annoying (but harmless) error
-        messages during shutdown. The problem is that CPython nullifies the
-        global state _before_ shutting down daemon threads, so that exceptions
-        might happen, and then `Thread.__bootstrap_inner` prints them out.
+        We're overriding ``Thread.run`` in order to avoid annoying (but harmless) error messages
+        during shutdown. The problem is that CPython nullifies the global state _before_ shutting
+        down daemon threads, so that exceptions might happen, and then ``Thread.__bootstrap_inner``
+        prints them out.
 
         Our solution is to swallow these exceptions here.
 
-        The side effect is that uncaught exceptions in our own thread code will _not_
-        be printed out as usual, so it's our responsibility to catch them in our
-        code.
+        The side effect is that uncaught exceptions in our own thread code will _not_ be printed out
+        as usual, so it's our responsibility to catch them in our code.
         """
 
         try:
@@ -54,6 +58,7 @@ class DaemonThread(Thread):
             # Exceptions might occur in daemon threads during interpreter shutdown
             pass
 
+
 # https://gist.github.com/tliron/81dd915166b0bfc64be08b4f8e22c835
 class FixedThreadPoolExecutor(object):
     """
@@ -77,8 +82,8 @@ class FixedThreadPoolExecutor(object):
         executor.raise_first()
         print executor.returns
 
-    You can also use it with the Python "with" keyword, in which case you don't need to call "close"
-    explicitly::
+    You can also use it with the Python ``with`` keyword, in which case you don't need to call
+    ``close`` explicitly::
 
         with FixedThreadPoolExecutor(10) as executor:
             for value in range(100):
@@ -95,11 +100,10 @@ class FixedThreadPoolExecutor(object):
                  timeout=None,
                  print_exceptions=False):
         """
-        :param size: Number of threads in the pool (fixed).
-        :param timeout: Timeout in seconds for all
-               blocking operations. (Defaults to none, meaning no timeout)
-        :param print_exceptions: Set to true in order to
-               print exceptions from tasks. (Defaults to false)
+        :param size: number of threads in the pool; if ``None`` will use an optimal number for the
+         platform
+        :param timeout: timeout in seconds for all blocking operations (``None`` means no timeout)
+        :param print_exceptions: set to ``True`` in order to print exceptions from tasks
         """
         if not size:
             try:
@@ -131,7 +135,7 @@ class FixedThreadPoolExecutor(object):
 
         The task will be called ASAP on the next available worker thread in the pool.
 
-        Will raise an :class:`ExecutorException` exception if cannot be submitted.
+        :raises ExecutorException: if cannot be submitted
         """
 
         try:
@@ -145,7 +149,7 @@ class FixedThreadPoolExecutor(object):
 
         You cannot submit tasks anymore after calling this.
 
-        This is called automatically upon exit if you are using the "with" keyword.
+        This is called automatically upon exit if you are using the ``with`` keyword.
         """
 
         self.drain()
@@ -194,9 +198,9 @@ class FixedThreadPoolExecutor(object):
         """
         If exceptions were thrown by any task, then the first one will be raised.
 
-        This is rather arbitrary: proper handling would involve iterating all the
-        exceptions. However, if you want to use the "raise" mechanism, you are
-        limited to raising only one of them.
+        This is rather arbitrary: proper handling would involve iterating all the exceptions.
+        However, if you want to use the "raise" mechanism, you are limited to raising only one of
+        them.
         """
 
         exceptions = self.exceptions
@@ -238,13 +242,13 @@ class FixedThreadPoolExecutor(object):
         self.close()
         return False
 
+
 class LockedList(list):
     """
-    A list that supports the "with" keyword with a built-in lock.
+    A list that supports the ``with`` keyword with a built-in lock.
 
-    Though Python lists are thread-safe in that they will not raise exceptions
-    during concurrent access, they do not guarantee atomicity. This class will
-    let you gain atomicity when needed.
+    Though Python lists are thread-safe in that they will not raise exceptions during concurrent
+    access, they do not guarantee atomicity. This class will let you gain atomicity when needed.
     """
 
     def __init__(self, *args, **kwargs):
@@ -260,7 +264,7 @@ class LockedList(list):
 
 class ExceptionThread(Thread):
     """
-    A thread from which top level exceptions can be retrieved or reraised
+    A thread from which top level exceptions can be retrieved or re-raised.
     """
     def __init__(self, *args, **kwargs):
         Thread.__init__(self, *args, **kwargs)



[11/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py b/aria/orchestrator/context/operation.py
index d43b847..7d5f40c 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Workflow and operation contexts
+Operation contexts.
 """
 
 import threading
@@ -27,7 +27,7 @@ from . import common
 
 class BaseOperationContext(common.BaseContext):
     """
-    Context object used during operation creation and execution
+    Base class for contexts used during operation creation and execution.
     """
 
     def __init__(self, task_id, actor_id, **kwargs):
@@ -116,7 +116,7 @@ class BaseOperationContext(common.BaseContext):
 
 class NodeOperationContext(BaseOperationContext):
     """
-    Context for node based operations.
+    Context for node operations.
     """
 
     @property
@@ -138,7 +138,7 @@ class NodeOperationContext(BaseOperationContext):
 
 class RelationshipOperationContext(BaseOperationContext):
     """
-    Context for relationship based operations.
+    Context for relationship operations.
     """
 
     @property

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/toolbelt.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/toolbelt.py b/aria/orchestrator/context/toolbelt.py
index b5a54a9..a2e1122 100644
--- a/aria/orchestrator/context/toolbelt.py
+++ b/aria/orchestrator/context/toolbelt.py
@@ -12,8 +12,9 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-Provides with different tools for operations.
+Tools for operations.
 """
 
 from . import operation
@@ -21,7 +22,7 @@ from . import operation
 
 class NodeToolBelt(object):
     """
-    Node operation related tool belt
+    Node operation tool belt.
     """
     def __init__(self, operation_context):
         self._op_context = operation_context
@@ -38,7 +39,7 @@ class NodeToolBelt(object):
 
 class RelationshipToolBelt(object):
     """
-    Relationship operation related tool belt
+    Relationship operation tool belt.
     """
     def __init__(self, operation_context):
         self._op_context = operation_context
@@ -46,9 +47,9 @@ class RelationshipToolBelt(object):
 
 def toolbelt(operation_context):
     """
-    Get a toolbelt according to the current operation executor
+    Get a toolbelt from to the current operation executor.
+
     :param operation_context:
-    :return:
     """
     if isinstance(operation_context, operation.NodeOperationContext):
         return NodeToolBelt(operation_context)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/context/workflow.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/workflow.py b/aria/orchestrator/context/workflow.py
index 18334f3..738d2fd 100644
--- a/aria/orchestrator/context/workflow.py
+++ b/aria/orchestrator/context/workflow.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Workflow and operation contexts
+Workflow context.
 """
 
 import threading
@@ -26,7 +26,7 @@ from .common import BaseContext
 
 class WorkflowContext(BaseContext):
     """
-    Context object used during workflow creation and execution
+    Context used during workflow creation and execution.
     """
     def __init__(self,
                  workflow_name,
@@ -57,21 +57,21 @@ class WorkflowContext(BaseContext):
     @property
     def execution(self):
         """
-        The execution model
+        Execution model.
         """
         return self.model.execution.get(self._execution_id)
 
     @execution.setter
     def execution(self, value):
         """
-        Store the execution in the model storage
+        Stores the execution in the storage model API ("MAPI").
         """
         self.model.execution.put(value)
 
     @property
     def node_templates(self):
         """
-        Iterator over nodes
+        Iterates over nodes templates.
         """
         key = 'service_{0}'.format(self.model.node_template.model_cls.name_column_name())
 
@@ -84,7 +84,7 @@ class WorkflowContext(BaseContext):
     @property
     def nodes(self):
         """
-        Iterator over node instances
+        Iterates over nodes.
         """
         key = 'service_{0}'.format(self.model.node.model_cls.name_column_name())
         return self.model.node.iter(
@@ -102,7 +102,7 @@ class WorkflowContext(BaseContext):
 
 class _CurrentContext(threading.local):
     """
-    Provides thread-level context, which sugarcoats the task mapi.
+    Provides a thread-level context, with sugar for the task MAPI.
     """
 
     def __init__(self):
@@ -114,9 +114,7 @@ class _CurrentContext(threading.local):
 
     def get(self):
         """
-        Retrieves the current workflow context
-        :return: the workflow context
-        :rtype: WorkflowContext
+        Retrieves the current workflow context.
         """
         if self._workflow_context is not None:
             return self._workflow_context
@@ -125,9 +123,7 @@ class _CurrentContext(threading.local):
     @contextmanager
     def push(self, workflow_context):
         """
-        Switches the current context to the provided context
-        :param workflow_context: the context to switch to.
-        :yields: the current context
+        Switches the current context to the provided context.
         """
         prev_workflow_context = self._workflow_context
         self._set(workflow_context)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/decorators.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/decorators.py b/aria/orchestrator/decorators.py
index 389bfb8..4b163d6 100644
--- a/aria/orchestrator/decorators.py
+++ b/aria/orchestrator/decorators.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Workflow and operation decorators
+Workflow and operation decorators.
 """
 
 from functools import partial, wraps
@@ -32,7 +32,7 @@ OPERATION_DECORATOR_RESERVED_ARGUMENTS = set(('ctx', 'toolbelt'))
 
 def workflow(func=None, suffix_template=''):
     """
-    Workflow decorator
+    Workflow decorator.
     """
     if func is None:
         return partial(workflow, suffix_template=suffix_template)
@@ -58,7 +58,7 @@ def workflow(func=None, suffix_template=''):
 
 def operation(func=None, toolbelt=False, suffix_template='', logging_handlers=None):
     """
-    Operation decorator
+    Operation decorator.
     """
 
     if func is None:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/events.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/events.py b/aria/orchestrator/events.py
index aa1b5bc..ef84e5d 100644
--- a/aria/orchestrator/events.py
+++ b/aria/orchestrator/events.py
@@ -14,10 +14,7 @@
 # limitations under the License.
 
 """
-ARIA's events Sub-Package
-Path: aria.events
-
-Events package provides events mechanism for different executions in aria.
+Orchestrator events.
 """
 
 from blinker import signal

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/exceptions.py b/aria/orchestrator/exceptions.py
index 71b6401..384458f 100644
--- a/aria/orchestrator/exceptions.py
+++ b/aria/orchestrator/exceptions.py
@@ -12,9 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
 """
-Orchestrator based exceptions
+Orchestrator exceptions.
 """
+
 from aria.exceptions import AriaError
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/__init__.py b/aria/orchestrator/execution_plugin/__init__.py
index 3624264..d15de99 100644
--- a/aria/orchestrator/execution_plugin/__init__.py
+++ b/aria/orchestrator/execution_plugin/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Execution plugin package.
+"""
+
 from contextlib import contextmanager
 from . import instantiation
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/common.py b/aria/orchestrator/execution_plugin/common.py
index 32e4575..ce6746c 100644
--- a/aria/orchestrator/execution_plugin/common.py
+++ b/aria/orchestrator/execution_plugin/common.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Execution plugin utilities.
+"""
+
 import json
 import os
 import tempfile
@@ -52,21 +56,23 @@ def download_script(ctx, script_path):
 
 def create_process_config(script_path, process, operation_kwargs, quote_json_env_vars=False):
     """
-    update a process with it's environment variables, and return it.
+    Updates a process with its environment variables, and return it.
+
+    Gets a dict representing a process and a dict representing the environment variables. Converts
+    each environment variable to a format of::
+
+        <string representing the name of the variable>:
+        <json formatted string representing the value of the variable>.
 
-    Get a dict representing a process and a dict representing the environment
-    variables. Convert each environment variable to a format of
-    <string representing the name of the variable> :
-    <json formatted string representing the value of the variable>.
-    Finally, update the process with the newly formatted environment variables,
-    and return the process.
+    Finally, updates the process with the newly formatted environment variables, and return the
+    process.
 
-    :param process: a dict representing a process
+    :param process: dict representing a process
     :type process: dict
-    :param operation_kwargs: a dict representing environment variables that
-    should exist in the process' running environment.
+    :param operation_kwargs: dict representing environment variables that should exist in the
+     process's running environment.
     :type operation_kwargs: dict
-    :return: the process updated with its environment variables.
+    :return: process updated with its environment variables
     :rtype: dict
     """
     process = process or {}

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/constants.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/constants.py b/aria/orchestrator/execution_plugin/constants.py
index 0b54dbe..8082e95 100644
--- a/aria/orchestrator/execution_plugin/constants.py
+++ b/aria/orchestrator/execution_plugin/constants.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Execution plugin constants.
+"""
+
 from . import exceptions
 
 # related to local

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/ctx_proxy/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/__init__.py b/aria/orchestrator/execution_plugin/ctx_proxy/__init__.py
index 7571c15..46c8cf1 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/__init__.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/__init__.py
@@ -13,4 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+``ctx`` proxy.
+"""
+
 from . import server, client

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/ctx_proxy/client.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/client.py b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
index f7f56aa..1310c21 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/client.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
@@ -14,6 +14,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+``ctx`` proxy client implementation.
+"""
+
 import argparse
 import json
 import os

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/ctx_proxy/server.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/server.py b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
index 50d4c3a..0a2a606 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/server.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+``ctx`` proxy server implementation.
+"""
+
 import collections
 import json
 import re

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/environment_globals.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/environment_globals.py b/aria/orchestrator/execution_plugin/environment_globals.py
index 27311f0..6dec293 100644
--- a/aria/orchestrator/execution_plugin/environment_globals.py
+++ b/aria/orchestrator/execution_plugin/environment_globals.py
@@ -13,41 +13,38 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for managing globals for the environment.
+"""
 
 def create_initial_globals(path):
-    """ emulates a `globals()` call in a freshly loaded module
-
-    The implementation of this function is likely to raise a couple of
-    questions. If you read the implementation and nothing bothered you, feel
-    free to skip the rest of this docstring.
-
-    First, why is this function in its own module and not, say, in the same
-    module of the other environment-related functions?
-    Second, why is it implemented in such a way that copies the globals, then
-    deletes the item that represents this function, and then changes some
-    other entries?
-
-    Well, these two questions can be answered with one (elaborate) explanation.
-    If this function was in the same module with the other environment-related
-    functions, then we would have had to delete more items in globals than just
-    `create_initial_globals`. That is because all of the other function names
-    would also be in globals, and since there is no built-in mechanism that
-    return the name of the user-defined objects, this approach is quite an
-    overkill.
-
-    - But why do we rely on the copy-existing-globals-and-delete-entries
-    method, when it seems to force us to put `create_initial_globals` in its
-    own file?
-
-    Well, because there is no easier method of creating globals of a newly
-    loaded module.
-
-    - How about hard coding a 'global' dict? It seems that there are very few
-    entries: __doc__, __file__, __name__, __package__ (but don't forget
-    __builtins__).
-
-    That would be coupling our implementation to a specific `globals`
-    implementation. What if `globals` were to change?
+    """
+    Emulates a ``globals()`` call in a freshly loaded module.
+
+    The implementation of this function is likely to raise a couple of questions. If you read the
+    implementation and nothing bothered you, feel free to skip the rest of this docstring.
+
+    First, why is this function in its own module and not, say, in the same module of the other
+    environment-related functions? Second, why is it implemented in such a way that copies the
+    globals, then deletes the item that represents this function, and then changes some other
+    entries?
+
+    Well, these two questions can be answered with one (elaborate) explanation. If this function was
+    in the same module with the other environment-related functions, then we would have had to
+    delete more items in globals than just ``create_initial_globals``. That is because all of the
+    other function names would also be in globals, and since there is no built-in mechanism that
+    return the name of the user-defined objects, this approach is quite an overkill.
+
+    *But why do we rely on the copy-existing-globals-and-delete-entries method, when it seems to
+    force us to put ``create_initial_globals`` in its own file?*
+
+    Well, because there is no easier method of creating globals of a newly loaded module.
+
+    *How about hard coding a ``globals`` dict? It seems that there are very few entries:
+    ``__doc__``, ``__file__``, ``__name__``, ``__package__`` (but don't forget ``__builtins__``).*
+
+    That would be coupling our implementation to a specific ``globals`` implementation. What if
+    ``globals`` were to change?
     """
     copied_globals = globals().copy()
     copied_globals.update({

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/exceptions.py b/aria/orchestrator/execution_plugin/exceptions.py
index 4641c80..f201fae 100644
--- a/aria/orchestrator/execution_plugin/exceptions.py
+++ b/aria/orchestrator/execution_plugin/exceptions.py
@@ -13,9 +13,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Execution plugin exceptions.
+"""
 
 class ProcessException(Exception):
-    """Raised when local scripts and remote ssh commands fail"""
+    """
+    Raised when local scripts and remote SSH commands fail.
+    """
 
     def __init__(self, stderr=None, stdout=None, command=None, exit_code=None):
         super(ProcessException, self).__init__(stderr)
@@ -26,11 +31,15 @@ class ProcessException(Exception):
 
 
 class TaskException(Exception):
-    """Raised when remote ssh scripts fail"""
+    """
+    Raised when remote ssh scripts fail.
+    """
 
 
 class ScriptException(Exception):
-    """Used by the ctx proxy server when task.retry or task.abort are called by scripts"""
+    """
+    Used by the ``ctx`` proxy server when task.retry or task.abort are called by scripts.
+    """
 
     def __init__(self, message=None, retry=None, retry_interval=None):
         super(ScriptException, self).__init__(message)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/instantiation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/instantiation.py b/aria/orchestrator/execution_plugin/instantiation.py
index b067e8c..f55aa50 100644
--- a/aria/orchestrator/execution_plugin/instantiation.py
+++ b/aria/orchestrator/execution_plugin/instantiation.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Instantiation of :class:`~aria.modeling.models.Operation` models.
+"""
+
 # TODO: this module will eventually be moved to a new "aria.instantiation" package
 
 from ...utils.type import full_type_name

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/local.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/local.py b/aria/orchestrator/execution_plugin/local.py
index 121e582..04b9ecd 100644
--- a/aria/orchestrator/execution_plugin/local.py
+++ b/aria/orchestrator/execution_plugin/local.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Local execution of operations.
+"""
+
 import os
 import subprocess
 import threading

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/operations.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/operations.py b/aria/orchestrator/execution_plugin/operations.py
index 0bc8083..e8de545 100644
--- a/aria/orchestrator/execution_plugin/operations.py
+++ b/aria/orchestrator/execution_plugin/operations.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Entry point functions.
+"""
+
 from aria.orchestrator import operation
 from . import local as local_operations
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/ssh/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ssh/__init__.py b/aria/orchestrator/execution_plugin/ssh/__init__.py
index ae1e83e..474deef 100644
--- a/aria/orchestrator/execution_plugin/ssh/__init__.py
+++ b/aria/orchestrator/execution_plugin/ssh/__init__.py
@@ -12,3 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+Remote execution of operations over SSH.
+"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/execution_plugin/ssh/operations.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ssh/operations.py b/aria/orchestrator/execution_plugin/ssh/operations.py
index 7147a30..c40e783 100644
--- a/aria/orchestrator/execution_plugin/ssh/operations.py
+++ b/aria/orchestrator/execution_plugin/ssh/operations.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Utilities for running commands remotely over SSH.
+"""
+
 import os
 import random
 import string

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/plugin.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/plugin.py b/aria/orchestrator/plugin.py
index 8fbcf5a..756a28e 100644
--- a/aria/orchestrator/plugin.py
+++ b/aria/orchestrator/plugin.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Plugin management.
+"""
+
 import os
 import tempfile
 import subprocess
@@ -32,7 +36,7 @@ class PluginManager(object):
 
     def __init__(self, model, plugins_dir):
         """
-        :param plugins_dir: Root directory to install plugins in.
+        :param plugins_dir: root directory in which to install plugins
         """
         self._model = model
         self._plugins_dir = plugins_dir
@@ -72,10 +76,13 @@ class PluginManager(object):
     def load_plugin(self, plugin, env=None):
         """
         Load the plugin into an environment.
+
         Loading the plugin means the plugin's code and binaries paths will be appended to the
-        environment's PATH and PYTHONPATH, thereby allowing usage of the plugin.
-        :param plugin: The plugin to load
-        :param env: The environment to load the plugin into; If `None`, os.environ will be used.
+        environment's ``PATH`` and ``PYTHONPATH``, thereby allowing usage of the plugin.
+
+        :param plugin: plugin to load
+        :param env: environment to load the plugin into; If ``None``, :obj:`os.environ` will be
+         used
         """
         env = env or os.environ
         plugin_dir = self.get_plugin_dir(plugin)
@@ -106,9 +113,10 @@ class PluginManager(object):
     @staticmethod
     def validate_plugin(source):
         """
-        validate a plugin archive.
-        A valid plugin is a wagon (http://github.com/cloudify-cosmo/wagon)
-        in the zip format (suffix may also be .wgn).
+        Validate a plugin archive.
+
+        A valid plugin is a `wagon <http://github.com/cloudify-cosmo/wagon>`__ in the zip format
+        (suffix may also be ``.wgn``).
         """
         if not zipfile.is_zipfile(source):
             raise exceptions.InvalidPluginError(

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflow_runner.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflow_runner.py b/aria/orchestrator/workflow_runner.py
index 3d58386..df1725f 100644
--- a/aria/orchestrator/workflow_runner.py
+++ b/aria/orchestrator/workflow_runner.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Workflow runner
+Running workflows.
 """
 
 import os
@@ -44,15 +44,16 @@ class WorkflowRunner(object):
         """
         Manages a single workflow execution on a given service.
 
-        :param workflow_name: Workflow name
-        :param service_id: Service ID
-        :param inputs: A key-value dict of inputs for the execution
-        :param model_storage: Model storage
-        :param resource_storage: Resource storage
-        :param plugin_manager: Plugin manager
-        :param executor: Executor for tasks. Defaults to a ProcessExecutor instance.
-        :param task_max_attempts: Maximum attempts of repeating each failing task
-        :param task_retry_interval: Retry interval in between retry attempts of a failing task
+        :param workflow_name: workflow name
+        :param service_id: service ID
+        :param inputs: key-value dict of inputs for the execution
+        :param model_storage: model storage API ("MAPI")
+        :param resource_storage: resource storage API ("RAPI")
+        :param plugin_manager: plugin manager
+        :param executor: executor for tasks; defaults to a
+         :class:`~aria.orchestrator.workflows.executor.process.ProcessExecutor` instance
+        :param task_max_attempts: maximum attempts of repeating each failing task
+        :param task_retry_interval: retry interval between retry attempts of a failing task
         """
 
         if not (execution_id or (workflow_name and service_id)):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/__init__.py b/aria/orchestrator/workflows/__init__.py
index e0c979a..1f6c368 100644
--- a/aria/orchestrator/workflows/__init__.py
+++ b/aria/orchestrator/workflows/__init__.py
@@ -13,5 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Workflows package.
+"""
+
 # Import required so that logging signals are registered
 from . import events_logging

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/api/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/__init__.py b/aria/orchestrator/workflows/api/__init__.py
index a3a17ee..587eee3 100644
--- a/aria/orchestrator/workflows/api/__init__.py
+++ b/aria/orchestrator/workflows/api/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Provides API for building tasks
+Workflow API.
 """
 
 from . import task, task_graph

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index f7d2c66..4c518fc 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -26,7 +26,7 @@ from .. import exceptions
 
 class BaseTask(object):
     """
-    Abstract task graph task
+    Base class for tasks.
     """
 
     def __init__(self, ctx=None, **kwargs):
@@ -39,44 +39,43 @@ class BaseTask(object):
     @property
     def id(self):
         """
-        uuid4 generated id
-        :return:
+        UUID4 ID.
         """
         return self._id
 
     @property
     def workflow_context(self):
         """
-        the context of the current workflow
-        :return:
+        Context of the current workflow.
         """
         return self._workflow_context
 
 
 class OperationTask(BaseTask):
     """
-    Represents an operation task in the task graph.
+    Executes an operation.
 
     :ivar name: formatted name (includes actor type, actor name, and interface/operation names)
     :vartype name: basestring
     :ivar actor: node or relationship
-    :vartype actor: :class:`aria.modeling.models.Node`|:class:`aria.modeling.models.Relationship`
+    :vartype actor: :class:`~aria.modeling.models.Node` or
+     :class:`~aria.modeling.models.Relationship`
     :ivar interface_name: interface name on actor
     :vartype interface_name: basestring
     :ivar operation_name: operation name on interface
     :vartype operation_name: basestring
     :ivar plugin: plugin (or None for default plugin)
-    :vartype plugin: :class:`aria.modeling.models.Plugin`
+    :vartype plugin: :class:`~aria.modeling.models.Plugin`
     :ivar function: path to Python function
     :vartype function: basestring
     :ivar arguments: arguments to send to Python function
-    :vartype arguments: {basestring, :class:`aria.modeling.models.Argument`}
+    :vartype arguments: {:obj:`basestring`: :class:`~aria.modeling.models.Argument`}
     :ivar ignore_failure: whether to ignore failures
     :vartype ignore_failure: bool
     :ivar max_attempts: maximum number of attempts allowed in case of failure
     :vartype max_attempts: int
     :ivar retry_interval: interval between retries (in seconds)
-    :vartype retry_interval: int
+    :vartype retry_interval: float
     """
 
     NAME_FORMAT = '{interface}:{operation}@{type}:{name}'
@@ -91,21 +90,22 @@ class OperationTask(BaseTask):
                  retry_interval=None):
         """
         :param actor: node or relationship
-        :type actor: :class:`aria.modeling.models.Node`|:class:`aria.modeling.models.Relationship`
+        :type actor: :class:`~aria.modeling.models.Node` or
+         :class:`~aria.modeling.models.Relationship`
         :param interface_name: interface name on actor
         :type interface_name: basestring
         :param operation_name: operation name on interface
         :type operation_name: basestring
         :param arguments: override argument values
-        :type arguments: {basestring, object}
+        :type arguments: {:obj:`basestring`: object}
         :param ignore_failure: override whether to ignore failures
         :type ignore_failure: bool
         :param max_attempts: override maximum number of attempts allowed in case of failure
         :type max_attempts: int
         :param retry_interval: override interval between retries (in seconds)
-        :type retry_interval: int
-        :raises aria.orchestrator.workflows.exceptions.OperationNotFoundException: if
-                ``interface_name`` and ``operation_name`` to not refer to an operation on the actor
+        :type retry_interval: float
+        :raises ~aria.orchestrator.workflows.exceptions.OperationNotFoundException: if
+         ``interface_name`` and ``operation_name`` do not refer to an operation on the actor
         """
 
         # Creating OperationTask directly should raise an error when there is no
@@ -160,14 +160,13 @@ class StubTask(BaseTask):
 
 class WorkflowTask(BaseTask):
     """
-    Represents a workflow task in the task graph
+    Executes a complete workflow.
     """
 
     def __init__(self, workflow_func, **kwargs):
         """
-        Creates a workflow based task using the workflow_func provided, and its kwargs
-        :param workflow_func: the function to run
-        :param kwargs: the kwargs that would be passed to the workflow_func
+        :param workflow_func: function to run
+        :param kwargs: kwargs that would be passed to the workflow_func
         """
         super(WorkflowTask, self).__init__(**kwargs)
         kwargs['ctx'] = self.workflow_context
@@ -176,8 +175,7 @@ class WorkflowTask(BaseTask):
     @property
     def graph(self):
         """
-        The graph constructed by the sub workflow
-        :return:
+        Graph constructed by the sub workflow.
         """
         return self._graph
 
@@ -190,13 +188,14 @@ class WorkflowTask(BaseTask):
 
 def create_task(actor, interface_name, operation_name, **kwargs):
     """
-    This helper function enables safe creation of OperationTask, if the supplied interface or
-    operation do not exist, None is returned.
-    :param actor: the actor for this task
-    :param interface_name: the name of the interface
-    :param operation_name: the name of the operation
-    :param kwargs: any additional kwargs to be passed to the task OperationTask
-    :return: and OperationTask or None (if the interface/operation does not exists)
+    Helper function that enables safe creation of :class:`OperationTask`. If the supplied interface
+    or operation do not exist, ``None`` is returned.
+
+    :param actor: actor for this task
+    :param interface_name: name of the interface
+    :param operation_name: name of the operation
+    :param kwargs: any additional kwargs to be passed to the OperationTask
+    :return: OperationTask or None (if the interface/operation does not exists)
     """
     try:
         return OperationTask(
@@ -212,13 +211,13 @@ def create_task(actor, interface_name, operation_name, **kwargs):
 def create_relationships_tasks(
         node, interface_name, source_operation_name=None, target_operation_name=None, **kwargs):
     """
-    Creates a relationship task (source and target) for all of a node_instance relationships.
-    :param basestring source_operation_name: the relationship operation name.
-    :param basestring interface_name: the name of the interface.
+    Creates a relationship task (source and target) for all of a node relationships.
+
+    :param basestring source_operation_name: relationship operation name
+    :param basestring interface_name: name of the interface
     :param source_operation_name:
     :param target_operation_name:
-    :param NodeInstance node: the source_node
-    :return:
+    :param node: source node
     """
     sub_tasks = []
     for relationship in node.outbound_relationships:
@@ -235,12 +234,11 @@ def create_relationships_tasks(
 def create_relationship_tasks(relationship, interface_name, source_operation_name=None,
                               target_operation_name=None, **kwargs):
     """
-    Creates a relationship task source and target.
-    :param Relationship relationship: the relationship instance itself
+    Creates a relationship task (source and target).
+
+    :param relationship: relationship instance itself
     :param source_operation_name:
     :param target_operation_name:
-
-    :return:
     """
     operations = []
     if source_operation_name:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/api/task_graph.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task_graph.py b/aria/orchestrator/workflows/api/task_graph.py
index 9f0d13b..900a0d1 100644
--- a/aria/orchestrator/workflows/api/task_graph.py
+++ b/aria/orchestrator/workflows/api/task_graph.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Task graph. Used by users to build workflows
+Task graph.
 """
 
 from collections import Iterable
@@ -27,7 +27,7 @@ from . import task as api_task
 
 class TaskNotInGraphError(Exception):
     """
-    An error representing a scenario where a given task is not in the graph as expected
+    An error representing a scenario where a given task is not in the graph as expected.
     """
     pass
 
@@ -43,8 +43,7 @@ def _filter_out_empty_tasks(func=None):
 
 class TaskGraph(object):
     """
-    A tasks graph builder.
-    Build an operations flow graph
+    Task graph builder.
     """
 
     def __init__(self, name):
@@ -59,8 +58,7 @@ class TaskGraph(object):
     @property
     def id(self):
         """
-        Represents the id of the graph
-        :return: graph id
+        ID of the graph
         """
         return self._id
 
@@ -69,27 +67,28 @@ class TaskGraph(object):
     @property
     def tasks(self):
         """
-        An iterator on tasks added to the graph
-        :yields: Iterator over all tasks in the graph
+        Iterator over tasks in the graph.
         """
         for _, data in self._graph.nodes_iter(data=True):
             yield data['task']
 
     def topological_order(self, reverse=False):
         """
-        Returns topological sort on the graph
+        Topological sort of the graph.
+
         :param reverse: whether to reverse the sort
-        :return: a list which represents the topological sort
+        :return: list which represents the topological sort
         """
         for task_id in topological_sort(self._graph, reverse=reverse):
             yield self.get_task(task_id)
 
     def get_dependencies(self, dependent_task):
         """
-        Iterates over the task's dependencies
-        :param BaseTask dependent_task: The task whose dependencies are requested
-        :yields: Iterator over all tasks which dependency_task depends on
-        :raise: TaskNotInGraphError if dependent_task is not in the graph
+        Iterates over the task's dependencies.
+
+        :param dependent_task: task whose dependencies are requested
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if
+         ``dependent_task`` is not in the graph
         """
         if not self.has_tasks(dependent_task):
             raise TaskNotInGraphError('Task id: {0}'.format(dependent_task.id))
@@ -98,10 +97,11 @@ class TaskGraph(object):
 
     def get_dependents(self, dependency_task):
         """
-        Iterates over the task's dependents
-        :param BaseTask dependency_task: The task whose dependents are requested
-        :yields: Iterator over all tasks which depend on dependency_task
-        :raise: TaskNotInGraphError if dependency_task is not in the graph
+        Iterates over the task's dependents.
+
+        :param dependency_task: task whose dependents are requested
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if
+         ``dependency_task`` is not in the graph
         """
         if not self.has_tasks(dependency_task):
             raise TaskNotInGraphError('Task id: {0}'.format(dependency_task.id))
@@ -112,11 +112,11 @@ class TaskGraph(object):
 
     def get_task(self, task_id):
         """
-        Get a task instance that's been inserted to the graph by the task's id
-        :param basestring task_id: The task's id
-        :return: Requested task
-        :rtype: BaseTask
-        :raise: TaskNotInGraphError if no task found in the graph with the given id
+        Get a task instance that's been inserted to the graph by the task's ID.
+
+        :param basestring task_id: task ID
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if no task found in
+         the graph with the given ID
         """
         if not self._graph.has_node(task_id):
             raise TaskNotInGraphError('Task id: {0}'.format(task_id))
@@ -126,9 +126,10 @@ class TaskGraph(object):
     @_filter_out_empty_tasks
     def add_tasks(self, *tasks):
         """
-        Add a task to the graph
-        :param BaseTask task: The task
-        :return: A list of added tasks
+        Adds a task to the graph.
+
+        :param task: task
+        :return: list of added tasks
         :rtype: list
         """
         assert all([isinstance(task, (api_task.BaseTask, Iterable)) for task in tasks])
@@ -146,9 +147,10 @@ class TaskGraph(object):
     @_filter_out_empty_tasks
     def remove_tasks(self, *tasks):
         """
-        Remove the provided task from the graph
-        :param BaseTask task: The task
-        :return: A list of removed tasks
+        Removes the provided task from the graph.
+
+        :param task: task
+        :return: list of removed tasks
         :rtype: list
         """
         return_tasks = []
@@ -165,9 +167,10 @@ class TaskGraph(object):
     @_filter_out_empty_tasks
     def has_tasks(self, *tasks):
         """
-        Check whether a task is in the graph or not
-        :param BaseTask task: The task
-        :return: True if all tasks are in the graph, otherwise True
+        Checks whether a task is in the graph.
+
+        :param task: task
+        :return: ``True`` if all tasks are in the graph, otherwise ``False``
         :rtype: list
         """
         assert all(isinstance(t, (api_task.BaseTask, Iterable)) for t in tasks)
@@ -183,16 +186,18 @@ class TaskGraph(object):
 
     def add_dependency(self, dependent, dependency):
         """
-        Add a dependency for one item (task, sequence or parallel) on another
-        The dependent will only be executed after the dependency terminates
-        If either of the items is either a sequence or a parallel,
-         multiple dependencies may be added
-        :param BaseTask|_TasksArrangement dependent: The dependent (task, sequence or parallel)
-        :param BaseTask|_TasksArrangement dependency: The dependency (task, sequence or parallel)
-        :return: True if the dependency between the two hadn't already existed, otherwise False
+        Adds a dependency for one item (task, sequence or parallel) on another.
+
+        The dependent will only be executed after the dependency terminates. If either of the items
+        is either a sequence or a parallel, multiple dependencies may be added.
+
+        :param dependent: dependent (task, sequence or parallel)
+        :param dependency: dependency (task, sequence or parallel)
+        :return: ``True`` if the dependency between the two hadn't already existed, otherwise
+         ``False``
         :rtype: bool
-        :raise TaskNotInGraphError if either the dependent or dependency are tasks which
-         are not in the graph
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if either the
+         dependent or dependency are tasks which are not in the graph
         """
         if not (self.has_tasks(dependent) and self.has_tasks(dependency)):
             raise TaskNotInGraphError()
@@ -212,18 +217,17 @@ class TaskGraph(object):
 
     def has_dependency(self, dependent, dependency):
         """
-        Check whether one item (task, sequence or parallel) depends on another
+        Checks whether one item (task, sequence or parallel) depends on another.
 
-        Note that if either of the items is either a sequence or a parallel,
-        and some of the dependencies exist in the graph but not all of them,
-        this method will return False
+        Note that if either of the items is either a sequence or a parallel, and some of the
+        dependencies exist in the graph but not all of them, this method will return ``False``.
 
-        :param BaseTask|_TasksArrangement dependent: The dependent (task, sequence or parallel)
-        :param BaseTask|_TasksArrangement dependency: The dependency (task, sequence or parallel)
-        :return: True if the dependency between the two exists, otherwise False
+        :param dependent: dependent (task, sequence or parallel)
+        :param dependency: dependency (task, sequence or parallel)
+        :return: ``True`` if the dependency between the two exists, otherwise ``False``
         :rtype: bool
-        :raise TaskNotInGraphError if either the dependent or dependency are tasks
-         which are not in the graph
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if either the
+         dependent or dependency are tasks which are not in the graph
         """
         if not (dependent and dependency):
             return False
@@ -246,18 +250,18 @@ class TaskGraph(object):
 
     def remove_dependency(self, dependent, dependency):
         """
-        Remove a dependency for one item (task, sequence or parallel) on another
+        Removes a dependency for one item (task, sequence or parallel) on another.
 
-        Note that if either of the items is either a sequence or a parallel, and some of
-        the dependencies exist in the graph but not all of them, this method will not remove
-        any of the dependencies and return False
+        Note that if either of the items is either a sequence or a parallel, and some of the
+        dependencies exist in the graph but not all of them, this method will not remove any of the
+        dependencies and return ``False``.
 
-        :param BaseTask|_TasksArrangement dependent: The dependent (task, sequence or parallel)
-        :param BaseTask|_TasksArrangement dependency: The dependency (task, sequence or parallel)
-        :return: False if the dependency between the two hadn't existed, otherwise True
+        :param dependent: dependent (task, sequence or parallel)
+        :param dependency: dependency (task, sequence or parallel)
+        :return: ``False`` if the dependency between the two hadn't existed, otherwise ``True``
         :rtype: bool
-        :raise TaskNotInGraphError if either the dependent or dependency are tasks
-         which are not in the graph
+        :raises ~aria.orchestrator.workflows.api.task_graph.TaskNotInGraphError: if either the
+         dependent or dependency are tasks which are not in the graph
         """
         if not (self.has_tasks(dependent) and self.has_tasks(dependency)):
             raise TaskNotInGraphError()
@@ -277,9 +281,10 @@ class TaskGraph(object):
     @_filter_out_empty_tasks
     def sequence(self, *tasks):
         """
-        Create and insert a sequence into the graph, effectively each task i depends on i-1
-        :param tasks: an iterable of dependencies
-        :return: the provided tasks
+        Creates and inserts a sequence into the graph, effectively each task i depends on i-1.
+
+        :param tasks: iterable of dependencies
+        :return: provided tasks
         """
         if tasks:
             self.add_tasks(*tasks)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/__init__.py b/aria/orchestrator/workflows/builtin/__init__.py
index 8b13c62..1b2f390 100644
--- a/aria/orchestrator/workflows/builtin/__init__.py
+++ b/aria/orchestrator/workflows/builtin/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-A set of builtin workflows
+Built-in workflows.
 """
 
 from .install import install

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/execute_operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/execute_operation.py b/aria/orchestrator/workflows/builtin/execute_operation.py
index 437e584..949f864 100644
--- a/aria/orchestrator/workflows/builtin/execute_operation.py
+++ b/aria/orchestrator/workflows/builtin/execute_operation.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Builtin execute_operation workflow
+Built-in operation execution Workflow.
 """
 
 from ... import workflow
@@ -34,13 +34,13 @@ def execute_operation(
         node_ids,
         **kwargs):
     """
-    The execute_operation workflow
+    Built-in operation execution Workflow.
 
-    :param WorkflowContext workflow_context: the workflow context
-    :param TaskGraph graph: the graph which will describe the workflow.
-    :param basestring operation: the operation name to execute
-    :param dict operation_kwargs:
-    :param bool run_by_dependency_order:
+    :param workflow_context: workflow context
+    :param graph: graph which will describe the workflow
+    :param operation: operation name to execute
+    :param operation_kwargs:
+    :param run_by_dependency_order:
     :param type_names:
     :param node_template_ids:
     :param node_ids:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/heal.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/heal.py b/aria/orchestrator/workflows/builtin/heal.py
index ca382e8..07e27b1 100644
--- a/aria/orchestrator/workflows/builtin/heal.py
+++ b/aria/orchestrator/workflows/builtin/heal.py
@@ -16,7 +16,7 @@
 # pylint: skip-file
 
 """
-Builtin heal workflow
+Built-in heal workflow.
 """
 
 from aria import workflow
@@ -28,11 +28,11 @@ from ..api import task
 @workflow
 def heal(ctx, graph, node_id):
     """
-    The heal workflow
+    Built-in heal workflow..
 
-    :param WorkflowContext ctx: the workflow context
-    :param TaskGraph graph: the graph which will describe the workflow.
-    :param node_id: the id of the node to heal
+    :param ctx: workflow context
+    :param graph: graph which will describe the workflow.
+    :param node_id: ID of the node to heal
     :return:
     """
     failing_node = ctx.model.node.get(node_id)
@@ -60,13 +60,12 @@ def heal(ctx, graph, node_id):
 @workflow(suffix_template='{failing_nodes}')
 def heal_uninstall(ctx, graph, failing_nodes, targeted_nodes):
     """
-    the uninstall part of the heal mechanism
-    :param WorkflowContext ctx: the workflow context
-    :param TaskGraph graph: the task graph to edit.
-    :param failing_nodes: the failing nodes to heal.
-    :param targeted_nodes: the targets of the relationships where the failing node are
-    source
-    :return:
+    Uninstall phase of the heal mechanism.
+
+    :param ctx: workflow context
+    :param graph: task graph to edit
+    :param failing_nodes: failing nodes to heal
+    :param targeted_nodes: targets of the relationships where the failing node are
     """
     node_sub_workflows = {}
 
@@ -113,13 +112,12 @@ def heal_uninstall(ctx, graph, failing_nodes, targeted_nodes):
 @workflow(suffix_template='{failing_nodes}')
 def heal_install(ctx, graph, failing_nodes, targeted_nodes):
     """
-    the install part of the heal mechanism
-    :param WorkflowContext ctx: the workflow context
-    :param TaskGraph graph: the task graph to edit.
-    :param failing_nodes: the failing nodes to heal.
-    :param targeted_nodes: the targets of the relationships where the failing node are
-    source
-    :return:
+    Install phase of the heal mechanism.
+
+    :param ctx: workflow context
+    :param graph: task graph to edit.
+    :param failing_nodes: failing nodes to heal
+    :param targeted_nodes: targets of the relationships where the failing node are
     """
     node_sub_workflows = {}
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/install.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/install.py b/aria/orchestrator/workflows/builtin/install.py
index 821b190..1e7c531 100644
--- a/aria/orchestrator/workflows/builtin/install.py
+++ b/aria/orchestrator/workflows/builtin/install.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Builtin install workflow
+Built-in install workflow.
 """
 
 from ... import workflow
@@ -24,6 +24,9 @@ from . import workflows
 
 @workflow
 def install(ctx, graph):
+    """
+    Built-in install workflow.
+    """
     tasks_and_nodes = []
     for node in ctx.nodes:
         tasks_and_nodes.append((api_task.WorkflowTask(workflows.install_node, node=node), node))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/start.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/start.py b/aria/orchestrator/workflows/builtin/start.py
index 1946143..c02a26d 100644
--- a/aria/orchestrator/workflows/builtin/start.py
+++ b/aria/orchestrator/workflows/builtin/start.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Builtin start workflow
+Built-in start workflow.
 """
 
 from .workflows import start_node
@@ -24,5 +24,8 @@ from ..api import task as api_task
 
 @workflow
 def start(ctx, graph):
+    """
+    Built-in start workflow.
+    """
     for node in ctx.model.node.iter():
         graph.add_tasks(api_task.WorkflowTask(start_node, node=node))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/stop.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/stop.py b/aria/orchestrator/workflows/builtin/stop.py
index c1b60ae..6f9930b 100644
--- a/aria/orchestrator/workflows/builtin/stop.py
+++ b/aria/orchestrator/workflows/builtin/stop.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Builtin stop workflow
+Built-in stop workflow.
 """
 
 from .workflows import stop_node
@@ -24,5 +24,8 @@ from ... import workflow
 
 @workflow
 def stop(ctx, graph):
+    """
+    Built-in stop workflow.
+    """
     for node in ctx.model.node.iter():
         graph.add_tasks(api_task.WorkflowTask(stop_node, node=node))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/builtin/uninstall.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/uninstall.py b/aria/orchestrator/workflows/builtin/uninstall.py
index c35117e..7925f4b 100644
--- a/aria/orchestrator/workflows/builtin/uninstall.py
+++ b/aria/orchestrator/workflows/builtin/uninstall.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Builtin uninstall workflow
+Built-in uninstall workflow.
 """
 
 from ... import workflow
@@ -24,6 +24,9 @@ from . import workflows
 
 @workflow
 def uninstall(ctx, graph):
+    """
+    Built-in uninstall workflow.
+    """
     tasks_and_nodes = []
     for node in ctx.nodes:
         tasks_and_nodes.append((api_task.WorkflowTask(workflows.uninstall_node, node=node), node))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/core/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/__init__.py b/aria/orchestrator/workflows/core/__init__.py
index 81db43f..3f28136 100644
--- a/aria/orchestrator/workflows/core/__init__.py
+++ b/aria/orchestrator/workflows/core/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Core for the workflow execution mechanism
+Workflow core.
 """
 
 from . import engine

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/core/compile.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/compile.py b/aria/orchestrator/workflows/core/compile.py
new file mode 100644
index 0000000..e405715
--- /dev/null
+++ b/aria/orchestrator/workflows/core/compile.py
@@ -0,0 +1,120 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Workflow compilation.
+"""
+
+from ....modeling import models
+from .. import executor, api
+
+
+def create_execution_tasks(ctx, task_graph, default_executor):
+    execution = ctx.execution
+    _construct_execution_tasks(execution, task_graph, default_executor)
+    ctx.model.execution.update(execution)
+    return execution.tasks
+
+
+def _construct_execution_tasks(execution,
+                               task_graph,
+                               default_executor,
+                               stub_executor=executor.base.StubTaskExecutor,
+                               start_stub_type=models.Task.START_WORKFLOW,
+                               end_stub_type=models.Task.END_WORKFLOW,
+                               depends_on=()):
+    """
+    Translates the user graph to the execution graph.
+
+    :param task_graph: user graph
+    :param start_stub_type: internal use
+    :param end_stub_type: internal use
+    :param depends_on: internal use
+    """
+    depends_on = list(depends_on)
+
+    # Insert start marker
+    start_task = models.Task(execution=execution,
+                             dependencies=depends_on,
+                             _api_id=_start_graph_suffix(task_graph.id),
+                             _stub_type=start_stub_type,
+                             _executor=stub_executor)
+
+    for task in task_graph.topological_order(reverse=True):
+        operation_dependencies = _get_tasks_from_dependencies(
+            execution, task_graph.get_dependencies(task), [start_task])
+
+        if isinstance(task, api.task.OperationTask):
+            models.Task.from_api_task(api_task=task,
+                                      executor=default_executor,
+                                      dependencies=operation_dependencies)
+
+        elif isinstance(task, api.task.WorkflowTask):
+            # Build the graph recursively while adding start and end markers
+            _construct_execution_tasks(
+                execution=execution,
+                task_graph=task,
+                default_executor=default_executor,
+                stub_executor=stub_executor,
+                start_stub_type=models.Task.START_SUBWROFKLOW,
+                end_stub_type=models.Task.END_SUBWORKFLOW,
+                depends_on=operation_dependencies
+            )
+        elif isinstance(task, api.task.StubTask):
+            models.Task(execution=execution,
+                        dependencies=operation_dependencies,
+                        _api_id=task.id,
+                        _executor=stub_executor,
+                        _stub_type=models.Task.STUB,
+                       )
+        else:
+            raise RuntimeError('Undefined state')
+
+    # Insert end marker
+    models.Task(dependencies=_get_non_dependent_tasks(execution) or [start_task],
+                execution=execution,
+                _api_id=_end_graph_suffix(task_graph.id),
+                _executor=stub_executor,
+                _stub_type=end_stub_type)
+
+
+def _start_graph_suffix(api_id):
+    return '{0}-Start'.format(api_id)
+
+
+def _end_graph_suffix(api_id):
+    return '{0}-End'.format(api_id)
+
+
+def _get_non_dependent_tasks(execution):
+    tasks_with_dependencies = set()
+    for task in execution.tasks:
+        tasks_with_dependencies.update(task.dependencies)
+    return list(set(execution.tasks) - set(tasks_with_dependencies))
+
+
+def _get_tasks_from_dependencies(execution, dependencies, default=()):
+    """
+    Returns task list from dependencies.
+    """
+    tasks = []
+    for dependency in dependencies:
+        if getattr(dependency, 'actor', False):
+            # This is
+            dependency_name = dependency.id
+        else:
+            dependency_name = _end_graph_suffix(dependency.id)
+        tasks.extend(task for task in execution.tasks if task._api_id == dependency_name)
+    return tasks or default

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/core/engine.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/engine.py b/aria/orchestrator/workflows/core/engine.py
index 5a94df8..d9c77e9 100644
--- a/aria/orchestrator/workflows/core/engine.py
+++ b/aria/orchestrator/workflows/core/engine.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-The workflow engine. Executes workflows
+Workflow execution.
 """
 
 import time
@@ -33,7 +33,7 @@ from . import events_handler  # pylint: disable=unused-import
 
 class Engine(logger.LoggerMixin):
     """
-    The workflow engine. Executes workflows
+    Executes workflows.
     """
 
     def __init__(self, executors, **kwargs):
@@ -43,7 +43,7 @@ class Engine(logger.LoggerMixin):
 
     def execute(self, ctx, resuming=False):
         """
-        execute the workflow
+        Executes the workflow.
         """
         if resuming:
             events.on_resume_workflow_signal.send(ctx)
@@ -87,8 +87,8 @@ class Engine(logger.LoggerMixin):
     def cancel_execution(ctx):
         """
         Send a cancel request to the engine. If execution already started, execution status
-        will be modified to 'cancelling' status. If execution is in pending mode, execution status
-        will be modified to 'cancelled' directly.
+        will be modified to ``cancelling`` status. If execution is in pending mode, execution status
+        will be modified to ``cancelled`` directly.
         """
         events.on_cancelling_workflow_signal.send(ctx)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/core/events_handler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/events_handler.py b/aria/orchestrator/workflows/core/events_handler.py
index 7380db8..769c1a8 100644
--- a/aria/orchestrator/workflows/core/events_handler.py
+++ b/aria/orchestrator/workflows/core/events_handler.py
@@ -14,10 +14,7 @@
 # limitations under the License.
 
 """
-ARIA's events Sub-Package
-Path: aria.events.storage_event_handler
-
-Implementation of storage handlers for workflow and operation events.
+Workflow event handling.
 """
 
 from datetime import (

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/events_logging.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/events_logging.py b/aria/orchestrator/workflows/events_logging.py
index 4cee867..9eee1e1 100644
--- a/aria/orchestrator/workflows/events_logging.py
+++ b/aria/orchestrator/workflows/events_logging.py
@@ -15,10 +15,7 @@
 
 
 """
-ARIA's events Sub-Package
-Path: aria.events.storage_event_handler
-
-Implementation of logger handlers for workflow and operation events.
+Workflow event logging.
 """
 
 from .. import events

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/exceptions.py b/aria/orchestrator/workflows/exceptions.py
index b5ae496..2a1d6b1 100644
--- a/aria/orchestrator/workflows/exceptions.py
+++ b/aria/orchestrator/workflows/exceptions.py
@@ -14,8 +14,9 @@
 # limitations under the License.
 
 """
-Workflow related Exception classes
+Workflow exceptions.
 """
+
 import os
 
 from .. import exceptions
@@ -23,14 +24,14 @@ from .. import exceptions
 
 class ExecutorException(exceptions.AriaError):
     """
-    General executor exception
+    General executor exception.
     """
     pass
 
 
 class ProcessException(ExecutorException):
     """
-    Raised when subprocess execution fails
+    Raised when subprocess execution fails.
     """
 
     def __init__(self, command, stderr=None, stdout=None, return_code=None):
@@ -62,13 +63,13 @@ class ProcessException(ExecutorException):
 
 class AriaEngineError(exceptions.AriaError):
     """
-    Raised by the workflow engine
+    Raised by the workflow engine.
     """
 
 
 class TaskException(exceptions.AriaError):
     """
-    Raised by the task
+    Raised by the task.
     """
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/__init__.py b/aria/orchestrator/workflows/executor/__init__.py
index 414a740..cafab74 100644
--- a/aria/orchestrator/workflows/executor/__init__.py
+++ b/aria/orchestrator/workflows/executor/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Executors for task execution
+Task executors.
 """
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/base.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/base.py b/aria/orchestrator/workflows/executor/base.py
index 4cc4503..ec1a0c7 100644
--- a/aria/orchestrator/workflows/executor/base.py
+++ b/aria/orchestrator/workflows/executor/base.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Base executor module
+Base class for task executors.
 """
 
 from aria import logger
@@ -23,14 +23,15 @@ from aria.orchestrator import events
 
 class BaseExecutor(logger.LoggerMixin):
     """
-    Base class for executors for running tasks
+    Base class for task executors.
     """
     def _execute(self, ctx):
         raise NotImplementedError
 
     def execute(self, ctx):
         """
-        Execute a task
+        Executes a task.
+
         :param task: task to execute
         """
         if ctx.task.function:
@@ -44,7 +45,7 @@ class BaseExecutor(logger.LoggerMixin):
 
     def close(self):
         """
-        Close the executor
+        Closes the executor.
         """
         pass
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/celery.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/celery.py b/aria/orchestrator/workflows/executor/celery.py
index 46b15fd..0716e5b 100644
--- a/aria/orchestrator/workflows/executor/celery.py
+++ b/aria/orchestrator/workflows/executor/celery.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Celery based executor
+Celery task executor.
 """
 
 import threading
@@ -25,7 +25,7 @@ from aria.orchestrator.workflows.executor import BaseExecutor
 
 class CeleryExecutor(BaseExecutor):
     """
-    Executor which runs tasks using aria_celery
+    Celery task executor.
     """
 
     def __init__(self, app, *args, **kwargs):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/dry.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/dry.py b/aria/orchestrator/workflows/executor/dry.py
index 9d86125..9314e5d 100644
--- a/aria/orchestrator/workflows/executor/dry.py
+++ b/aria/orchestrator/workflows/executor/dry.py
@@ -14,8 +14,9 @@
 # limitations under the License.
 
 """
-Dry executor
+Dry task executor.
 """
+
 from datetime import datetime
 
 from . import base
@@ -23,7 +24,7 @@ from . import base
 
 class DryExecutor(base.BaseExecutor):                                                                    # pylint: disable=abstract-method
     """
-    Executor which dry runs tasks - prints task information without causing any side effects
+    Dry task executor: prints task information without causing any side effects.
     """
     def execute(self, ctx):
         with ctx.persist_changes:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/process.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/process.py b/aria/orchestrator/workflows/executor/process.py
index 11e3cfd..69288ea 100644
--- a/aria/orchestrator/workflows/executor/process.py
+++ b/aria/orchestrator/workflows/executor/process.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Subprocess based executor
+Sub-process task executor.
 """
 
 # pylint: disable=wrong-import-position
@@ -67,7 +67,7 @@ _Task = namedtuple('_Task', 'proc, ctx')
 
 class ProcessExecutor(base.BaseExecutor):
     """
-    Executor which runs tasks in a subprocess environment
+    Sub-process task executor.
     """
 
     def __init__(self, plugin_manager=None, python_path=None, *args, **kwargs):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/orchestrator/workflows/executor/thread.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/thread.py b/aria/orchestrator/workflows/executor/thread.py
index 8c447b6..d9dcdf8 100644
--- a/aria/orchestrator/workflows/executor/thread.py
+++ b/aria/orchestrator/workflows/executor/thread.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Thread based executor
+Thread task executor.
 """
 
 import Queue
@@ -29,9 +29,11 @@ from .base import BaseExecutor
 
 class ThreadExecutor(BaseExecutor):
     """
-    Executor which runs tasks in a separate thread. It's easier writing tests
-    using this executor rather than the full blown subprocess executor.
-    Note: This executor is not capable of running plugin operations.
+    Thread task executor.
+
+    It's easier writing tests using this executor rather than the full-blown sub-process executor.
+
+    Note: This executor is incapable of running plugin operations.
     """
 
     def __init__(self, pool_size=1, *args, **kwargs):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/__init__.py b/aria/parser/__init__.py
index 64df88a..7903b52 100644
--- a/aria/parser/__init__.py
+++ b/aria/parser/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Parser package.
+"""
+
 from .specification import implements_specification, iter_specifications
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/consumption/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/__init__.py b/aria/parser/consumption/__init__.py
index 76e73be..bd4b29c 100644
--- a/aria/parser/consumption/__init__.py
+++ b/aria/parser/consumption/__init__.py
@@ -13,6 +13,37 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Consumption package.
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.consumption.ConsumptionContext
+   aria.parser.consumption.Style
+
+Consumers
+---------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.consumption.Consumer
+   aria.parser.consumption.ConsumerChain
+   aria.parser.consumption.ConsumerException
+   aria.parser.consumption.Inputs
+   aria.parser.consumption.ServiceTemplate
+   aria.parser.consumption.Types
+   aria.parser.consumption.CoerceServiceInstanceValues
+   aria.parser.consumption.ValidateServiceInstance
+   aria.parser.consumption.SatisfyRequirements
+   aria.parser.consumption.ValidateCapabilities
+   aria.parser.consumption.FindHosts
+   aria.parser.consumption.ConfigureOperations
+   aria.parser.consumption.ServiceInstance
+   aria.parser.consumption.Read
+   aria.parser.consumption.Validate
+"""
 
 from .exceptions import ConsumerException
 from .context import ConsumptionContext

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/consumption/consumer.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/consumer.py b/aria/parser/consumption/consumer.py
index f9c2f2e..4f4c614 100644
--- a/aria/parser/consumption/consumer.py
+++ b/aria/parser/consumption/consumer.py
@@ -48,8 +48,8 @@ class ConsumerChain(Consumer):
     """
     ARIA consumer chain.
 
-    Calls consumers in order, handling exception by calling `_handle_exception` on them,
-    and stops the chain if there are any validation issues.
+    Calls consumers in order, handling exception by calling ``_handle_exception`` on them, and stops
+    the chain if there are any validation issues.
     """
 
     def __init__(self, context, consumer_classes=None, handle_exceptions=True):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/consumption/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/context.py b/aria/parser/consumption/context.py
index a8b75df..6fa61f4 100644
--- a/aria/parser/consumption/context.py
+++ b/aria/parser/consumption/context.py
@@ -29,16 +29,22 @@ _thread_locals = threading.local()
 
 class ConsumptionContext(object):
     """
-    Properties:
-
-    * :code:`args`: The runtime arguments (usually provided on the command line)
-    * :code:`out`: Message output stream (defaults to stdout)
-    * :code:`style`: Message output style
-    * :code:`validation`: :class:`aria.validation.ValidationContext`
-    * :code:`loading`: :class:`aria.loading.LoadingContext`
-    * :code:`reading`: :class:`aria.reading.ReadingContext`
-    * :code:`presentation`: :class:`aria.presentation.PresentationContext`
-    * :code:`modeling`: :class:`aria.service.ModelingContext`
+    Consumption context.
+
+    :ivar args: runtime arguments (usually provided on the command line)
+    :ivar out: message output stream (defaults to stdout)
+    :ivar style: message output style
+    :vartype style: Style
+    :ivar validation: validation context
+    :vartype validation: :class:`ValidationContext`
+    :ivar loading: loading context
+    :vartype loading: :class:`LoadingContext`
+    :ivar reading: reading context
+    :vartype reading: :class:`ReadingContext`
+    :ivar presentation: presentation context
+    :vartype presentation: :class:`PresentationContext`
+    :ivar modeling: modeling context
+    :vartype modeling: :class:`ModelingContext`
     """
 
     @staticmethod
@@ -71,7 +77,7 @@ class ConsumptionContext(object):
 
     def write(self, string):
         """
-        Writes to our :code:`out`, making sure to encode UTF-8 if required.
+        Writes to our ``out``, making sure to encode UTF-8 if required.
         """
 
         try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/consumption/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/presentation.py b/aria/parser/consumption/presentation.py
index 7766473..542b3f0 100644
--- a/aria/parser/consumption/presentation.py
+++ b/aria/parser/consumption/presentation.py
@@ -26,11 +26,12 @@ class Read(Consumer):
     """
     Reads the presentation, handling imports recursively.
 
-    It works by consuming a data source via appropriate :class:`aria.loader.Loader`,
-    :class:`aria.reader.Reader`, and :class:`aria.presenter.Presenter` instances.
+    It works by consuming a data source via appropriate :class:`~aria.parser.loading.Loader`,
+    :class:`~aria.parser.reading.Reader`, and :class:`~aria.parser.presentation.Presenter`
+    instances.
 
     It supports agnostic raw data composition for presenters that have
-    :code:`_get_import_locations` and :code:`_merge_import`.
+    ``_get_import_locations`` and ``_merge_import``.
 
     To improve performance, loaders are called asynchronously on separate threads.
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/parser/exceptions.py b/aria/parser/exceptions.py
index 5d1a55c..a1f7012 100644
--- a/aria/parser/exceptions.py
+++ b/aria/parser/exceptions.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Parser exceptions.
+"""
+
 from ..exceptions import AriaException
 from .validation import Issue
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/__init__.py b/aria/parser/loading/__init__.py
index 006f164..834675e 100644
--- a/aria/parser/loading/__init__.py
+++ b/aria/parser/loading/__init__.py
@@ -13,6 +13,41 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Loading package.
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.loading.LoadingContext
+   aria.parser.loading.LoaderException
+   aria.parser.loading.LoaderNotFoundError
+   aria.parser.loading.DocumentNotFoundException
+   aria.parser.loading.LoaderSource
+   aria.parser.loading.DefaultLoaderSource
+
+Loaders
+-------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.loading.Loader
+   aria.parser.loading.FileTextLoader
+   aria.parser.loading.LiteralLoader
+   aria.parser.loading.RequestLoader
+   aria.parser.loading.RequestTextLoader
+   aria.parser.loading.UriTextLoader
+
+Locations
+---------
+
+.. autosummary::
+   :nosignatures:
+
+   aria.parser.loading.Location
+   aria.parser.loading.UriLocation
+"""
 
 from .exceptions import LoaderException, LoaderNotFoundError, DocumentNotFoundException
 from .context import LoadingContext

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/context.py b/aria/parser/loading/context.py
index 44e3fd1..59727c9 100644
--- a/aria/parser/loading/context.py
+++ b/aria/parser/loading/context.py
@@ -20,10 +20,12 @@ from .source import DefaultLoaderSource
 
 class LoadingContext(object):
     """
-    Properties:
+    Loading context.
 
-    * :code:`loader_source`: For finding loader instances
-    * :code:`prefixes`: List of additional prefixes for :class:`UriTextLoader`
+    :ivar loader_source: for finding loader instances
+    :vartype loader_source: ~aria.parser.loading.LoaderSource
+    :ivar prefixes: additional prefixes for :class:`UriTextLoader`
+    :vartype prefixes: [:obj:`basestring`]
     """
 
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/literal.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/literal.py b/aria/parser/loading/literal.py
index 1b99fd8..7865008 100644
--- a/aria/parser/loading/literal.py
+++ b/aria/parser/loading/literal.py
@@ -21,7 +21,7 @@ class LiteralLoader(Loader):
     """
     ARIA literal loader.
 
-    See :class:`aria.loading.LiteralLocation`.
+    See :class:`~aria.parser.loading.LiteralLocation`.
     """
 
     def __init__(self, location):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/location.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/location.py b/aria/parser/loading/location.py
index 5bc6fab..902e856 100644
--- a/aria/parser/loading/location.py
+++ b/aria/parser/loading/location.py
@@ -23,8 +23,8 @@ class Location(object):
     """
     Base class for ARIA locations.
 
-    Locations are used by :class:`aria.loading.LoaderSource` to delegate to
-    an appropriate :class:`aria.loading.Loader`.
+    Locations are used by :class:`~aria.parser.loading.LoaderSource` to delegate to
+    an appropriate :class:`~aria.parser.loading.Loader`.
     """
 
     def is_equivalent(self, location):
@@ -41,7 +41,7 @@ class UriLocation(Location):
 
     If no scheme is included, it should be treated as a filesystem path.
 
-    See :class:`aria.loading.UriTextLoader`.
+    See :class:`~aria.parser.loading.UriTextLoader`.
     """
 
     def __init__(self, uri):
@@ -68,7 +68,7 @@ class LiteralLocation(Location):
     """
     A location that embeds content.
 
-    See :class:`aria.loading.LiteralLoader`.
+    See :class:`~aria.parser.loading.LiteralLoader`.
     """
 
     def __init__(self, content, name='literal'):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/source.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/source.py b/aria/parser/loading/source.py
index 7acf813..bcd6dd1 100644
--- a/aria/parser/loading/source.py
+++ b/aria/parser/loading/source.py
@@ -32,7 +32,7 @@ class LoaderSource(object):
 class DefaultLoaderSource(LoaderSource):
     """
     The default ARIA loader source will generate a :class:`UriTextLoader` for
-    :class:`UriLocation' and a :class:`LiteralLoader` for a :class:`LiteralLocation`.
+    :class:`UriLocation` and a :class:`LiteralLoader` for a :class:`LiteralLocation`.
     """
 
     def get_loader(self, context, location, origin_location):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/loading/uri.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/uri.py b/aria/parser/loading/uri.py
index 1b23bf6..a5a18e6 100644
--- a/aria/parser/loading/uri.py
+++ b/aria/parser/loading/uri.py
@@ -29,14 +29,14 @@ class UriTextLoader(Loader):
     """
     Base class for ARIA URI loaders.
 
-    See :class:`aria.loading.UriLocation`.
+    See :class:`~aria.parser.loading.UriLocation`.
 
     Supports a list of search prefixes that are tried in order if the URI cannot be found.
     They will be:
 
-    * If :code:`origin_location` is provided its prefix will come first.
+    * If ``origin_location`` is provided its prefix will come first.
     * Then the prefixes in the :class:`LoadingContext` will be added.
-    * Finally, the global prefixes specified in :code:`URI_LOADER_PREFIXES` will be added.
+    * Finally, the parser can supply a ``uri_loader_prefix`` function with extra prefixes.
     """
 
     def __init__(self, context, location, origin_location=None):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/__init__.py b/aria/parser/modeling/__init__.py
index df127cd..4b1c995 100644
--- a/aria/parser/modeling/__init__.py
+++ b/aria/parser/modeling/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Modeling package.
+"""
+
 from .context import IdType, ModelingContext
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/parser/modeling/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/context.py b/aria/parser/modeling/context.py
index 4a53641..3d75617 100644
--- a/aria/parser/modeling/context.py
+++ b/aria/parser/modeling/context.py
@@ -38,14 +38,20 @@ class IdType(object):
 
 class ModelingContext(object):
     """
-    Properties:
-
-    * :code:`template`: The generated service template
-    * :code:`instance`: The generated service instance
-    * :code:`node_id_format`: Format for node instance IDs
-    * :code:`id_type`: Type of IDs to use for instances
-    * :code:`id_max_length`: Maximum allowed instance ID length
-    * :code:`inputs`: Dict of inputs values
+    Modeling context.
+
+    :ivar template: generated service template
+    :vartype template: aria.modeling.models.ServiceTemplate
+    :ivar instance: generated service instance
+    :vartype instance: aria.modeling.models.Service
+    :ivar node_id_format: format for node instance IDs
+    :vartype node_id_format: basestring
+    :ivar id_type: type of IDs to use for instances
+    :vartype id_type: basestring
+    :ivar id_max_length: maximum allowed instance ID length
+    :vartype id_max_length: int
+    :ivar inputs: inputs values
+    :vartype inputs: {:obj:`basestring`, object}
     """
 
     def __init__(self):


[03/15] incubator-ariatosca git commit: ARIA-280 Change package name

Posted by em...@apache.org.
ARIA-280 Change package name

Changed package name from 'aria' to 'apache-ariatosca',
in accordance with Apache's standards.
The CLI '--version' command will now also show the correct
package name.

Additionally, fixed the download_url field in setup.py -
it now includes an '-incubating' suffix.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/668ddcb7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/668ddcb7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/668ddcb7

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 668ddcb75a164ef8c119dff102a560e3f59daa7f
Parents: 51d0542
Author: Ran Ziv <ra...@gigaspaces.com>
Authored: Thu Jun 22 15:39:28 2017 +0300
Committer: Ran Ziv <ra...@gigaspaces.com>
Committed: Sun Jun 25 17:01:10 2017 +0300

----------------------------------------------------------------------
 README.rst            |  4 ++--
 aria/__init__.py      |  7 ++++---
 aria/cli/core/aria.py | 25 ++-----------------------
 setup.py              |  7 ++++---
 4 files changed, 12 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/668ddcb7/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index dc53d47..d4740cd 100644
--- a/README.rst
+++ b/README.rst
@@ -36,10 +36,10 @@ To install ARIA directly from PyPI (using a ``wheel``), use::
     pip install apache-ariatosca
 
 To install ARIA from source, download the source tarball from
-`PyPI <https://pypi.python.org/pypi/apache-ariatosca>`__, extract it, and run::
+`PyPI <https://pypi.python.org/pypi/apache-ariatosca>`__, extract and ``cd`` into the extract dir, and run::
 
     pip install --upgrade pip setuptools
-    pip install incubator-ariatosca
+    pip install .
 
 | The source package comes along with relevant examples, documentation, ``requirements.txt`` (for installing specifically the frozen dependencies' versions with which ARIA was tested) and more.
 |

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/668ddcb7/aria/__init__.py
----------------------------------------------------------------------
diff --git a/aria/__init__.py b/aria/__init__.py
index 34db3a8..bed1dc6 100644
--- a/aria/__init__.py
+++ b/aria/__init__.py
@@ -20,10 +20,11 @@ ARIA top level package
 import sys
 
 import pkg_resources
-__version__ = pkg_resources.get_distribution('aria').version
+aria_package_name = 'apache-ariatosca'
+__version__ = pkg_resources.get_distribution(aria_package_name).version
 
-from .orchestrator.decorators import workflow, operation
-from . import (
+from .orchestrator.decorators import workflow, operation  # pylint: disable=wrong-import-position
+from . import (  # pylint: disable=wrong-import-position
     extension,
     utils,
     parser,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/668ddcb7/aria/cli/core/aria.py
----------------------------------------------------------------------
diff --git a/aria/cli/core/aria.py b/aria/cli/core/aria.py
index 56fe2f7..331caca 100644
--- a/aria/cli/core/aria.py
+++ b/aria/cli/core/aria.py
@@ -13,11 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
 import os
 import sys
 import difflib
-import StringIO
 import traceback
 import inspect
 from functools import wraps
@@ -32,6 +30,7 @@ from .. import defaults
 from .. import helptexts
 from ..inputs import inputs_to_dict
 from ... import __version__
+from ... import aria_package_name
 from ...utils.exceptions import get_exception_as_string
 
 
@@ -94,31 +93,11 @@ def mutually_exclusive_option(*param_decls, **attrs):
     return decorator
 
 
-def _format_version_data(version,
-                         prefix=None,
-                         suffix=None,
-                         infix=None):
-    all_data = dict(version=version)
-    all_data['prefix'] = prefix or ''
-    all_data['suffix'] = suffix or ''
-    all_data['infix'] = infix or ''
-    output = StringIO.StringIO()
-    output.write('{prefix}{version}'.format(**all_data))
-    output.write('{suffix}'.format(**all_data))
-    return output.getvalue()
-
-
 def show_version(ctx, param, value):
     if not value:
         return
 
-    cli_version = _format_version_data(
-        __version__,
-        prefix='ARIA CLI ',
-        infix=' ' * 5,
-        suffix='')
-
-    logger.info(cli_version)
+    logger.info('{0} {1}'.format(aria_package_name, __version__))
     ctx.exit()
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/668ddcb7/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index d2a914c..340cce2 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ from setuptools.command.install import install
 from setuptools.command.develop import develop
 
 
-_PACKAGE_NAME = 'aria'
+_PACKAGE_NAME = 'apache-ariatosca'
 _PYTHON_SUPPORTED_VERSIONS = [(2, 6), (2, 7)]
 _EXTENSION_DIR = 'extensions'
 _EXTENSION_NAMES = [
@@ -38,6 +38,7 @@ root_dir = os.path.dirname(__file__)
 
 with open(os.path.join(root_dir, 'VERSION')) as version_file:
     __version__ = version_file.read().strip()
+    incubating_version = '{0}-incubating'.format(__version__)
 
 with open(os.path.join(root_dir, 'README.rst')) as readme:
     long_description = readme.read()
@@ -106,11 +107,11 @@ setup(
     description='ARIA',
     long_description=long_description,
     license='Apache License 2.0',
-    author='aria',
+    author='ARIA',
     author_email='dev@ariatosca.incubator.apache.org',
     url='http://ariatosca.incubator.apache.org/',
     download_url=(
-        'https://dist.apache.org/repos/dist/release/incubator/ariatosca/' + __version__),
+        'https://dist.apache.org/repos/dist/release/incubator/ariatosca/' + incubating_version),
     classifiers=[
         'Development Status :: 4 - Beta',
         'Environment :: Console',


[15/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
ARIA-286 Sphinx documentation for code and CLI


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/3f09ecde
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/3f09ecde
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/3f09ecde

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 3f09ecdeb45966f2f9e671ebf23892a9f6bb5c4b
Parents: 53dc64e
Author: Tal Liron <ta...@gmail.com>
Authored: Thu Jun 22 21:13:28 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Wed Jun 28 19:05:45 2017 -0500

----------------------------------------------------------------------
 aria/__init__.py                                |   14 +-
 aria/cli/__init__.py                            |    4 +
 aria/cli/color.py                               |    8 +-
 aria/cli/commands/__init__.py                   |    4 +
 aria/cli/commands/executions.py                 |   45 +-
 aria/cli/commands/logs.py                       |   22 +-
 aria/cli/commands/node_templates.py             |   21 +-
 aria/cli/commands/nodes.py                      |   23 +-
 aria/cli/commands/plugins.py                    |   38 +-
 aria/cli/commands/reset.py                      |   13 +-
 aria/cli/commands/service_templates.py          |   58 +-
 aria/cli/commands/services.py                   |   43 +-
 aria/cli/commands/workflows.py                  |   23 +-
 aria/cli/config/__init__.py                     |    4 +
 aria/cli/config/config.py                       |    3 +
 aria/cli/core/__init__.py                       |    4 +
 aria/cli/core/aria.py                           |   13 +-
 aria/cli/csar.py                                |    7 +
 aria/cli/defaults.py                            |   10 +
 aria/cli/env.py                                 |    3 +
 aria/cli/exceptions.py                          |    3 +
 aria/cli/execution_logging.py                   |    5 +
 aria/cli/helptexts.py                           |   19 +-
 aria/cli/inputs.py                              |   24 +-
 aria/cli/logger.py                              |    3 +
 aria/cli/main.py                                |   15 +-
 aria/cli/service_template_utils.py              |   64 +-
 aria/cli/table.py                               |   56 +-
 aria/cli/utils.py                               |   44 +-
 aria/core.py                                    |    4 +
 aria/exceptions.py                              |   10 +-
 aria/extension.py                               |   34 +-
 aria/logger.py                                  |   38 +-
 aria/modeling/__init__.py                       |    4 +
 aria/modeling/constraints.py                    |    5 +-
 aria/modeling/exceptions.py                     |    4 +
 aria/modeling/functions.py                      |   23 +-
 aria/modeling/mixins.py                         |  101 +-
 aria/modeling/models.py                         |  113 +-
 aria/modeling/orchestration.py                  |  612 ++++---
 aria/modeling/relationship.py                   |  120 +-
 aria/modeling/service_changes.py                |   83 +-
 aria/modeling/service_common.py                 |  364 ++--
 aria/modeling/service_instance.py               | 1527 ++++++++++-------
 aria/modeling/service_template.py               | 1562 +++++++++++-------
 aria/modeling/types.py                          |   49 +-
 aria/modeling/utils.py                          |   50 +-
 aria/orchestrator/__init__.py                   |    4 +-
 aria/orchestrator/context/__init__.py           |    2 +-
 aria/orchestrator/context/common.py             |   37 +-
 aria/orchestrator/context/exceptions.py         |    4 +-
 aria/orchestrator/context/operation.py          |    8 +-
 aria/orchestrator/context/toolbelt.py           |   11 +-
 aria/orchestrator/context/workflow.py           |   22 +-
 aria/orchestrator/decorators.py                 |    6 +-
 aria/orchestrator/events.py                     |    5 +-
 aria/orchestrator/exceptions.py                 |    4 +-
 aria/orchestrator/execution_plugin/__init__.py  |    4 +
 aria/orchestrator/execution_plugin/common.py    |   28 +-
 aria/orchestrator/execution_plugin/constants.py |    4 +
 .../execution_plugin/ctx_proxy/__init__.py      |    4 +
 .../execution_plugin/ctx_proxy/client.py        |    4 +
 .../execution_plugin/ctx_proxy/server.py        |    4 +
 .../execution_plugin/environment_globals.py     |   63 +-
 .../orchestrator/execution_plugin/exceptions.py |   15 +-
 .../execution_plugin/instantiation.py           |    4 +
 aria/orchestrator/execution_plugin/local.py     |    4 +
 .../orchestrator/execution_plugin/operations.py |    4 +
 .../execution_plugin/ssh/__init__.py            |    4 +
 .../execution_plugin/ssh/operations.py          |    4 +
 aria/orchestrator/plugin.py                     |   22 +-
 aria/orchestrator/workflow_runner.py            |   21 +-
 aria/orchestrator/workflows/__init__.py         |    4 +
 aria/orchestrator/workflows/api/__init__.py     |    2 +-
 aria/orchestrator/workflows/api/task.py         |   72 +-
 aria/orchestrator/workflows/api/task_graph.py   |  129 +-
 aria/orchestrator/workflows/builtin/__init__.py |    2 +-
 .../workflows/builtin/execute_operation.py      |   14 +-
 aria/orchestrator/workflows/builtin/heal.py     |   36 +-
 aria/orchestrator/workflows/builtin/install.py  |    5 +-
 aria/orchestrator/workflows/builtin/start.py    |    5 +-
 aria/orchestrator/workflows/builtin/stop.py     |    5 +-
 .../orchestrator/workflows/builtin/uninstall.py |    5 +-
 aria/orchestrator/workflows/core/__init__.py    |    2 +-
 aria/orchestrator/workflows/core/compile.py     |  120 ++
 aria/orchestrator/workflows/core/engine.py      |   10 +-
 .../workflows/core/events_handler.py            |    5 +-
 aria/orchestrator/workflows/events_logging.py   |    5 +-
 aria/orchestrator/workflows/exceptions.py       |   11 +-
 .../orchestrator/workflows/executor/__init__.py |    2 +-
 aria/orchestrator/workflows/executor/base.py    |    9 +-
 aria/orchestrator/workflows/executor/celery.py  |    4 +-
 aria/orchestrator/workflows/executor/dry.py     |    5 +-
 aria/orchestrator/workflows/executor/process.py |    4 +-
 aria/orchestrator/workflows/executor/thread.py  |   10 +-
 aria/parser/__init__.py                         |    4 +
 aria/parser/consumption/__init__.py             |   31 +
 aria/parser/consumption/consumer.py             |    4 +-
 aria/parser/consumption/context.py              |   28 +-
 aria/parser/consumption/presentation.py         |    7 +-
 aria/parser/exceptions.py                       |    4 +
 aria/parser/loading/__init__.py                 |   35 +
 aria/parser/loading/context.py                  |    8 +-
 aria/parser/loading/literal.py                  |    2 +-
 aria/parser/loading/location.py                 |    8 +-
 aria/parser/loading/source.py                   |    2 +-
 aria/parser/loading/uri.py                      |    6 +-
 aria/parser/modeling/__init__.py                |    4 +
 aria/parser/modeling/context.py                 |   22 +-
 aria/parser/presentation/__init__.py            |   84 +-
 aria/parser/presentation/context.py             |   28 +-
 aria/parser/presentation/field_validators.py    |   19 +-
 aria/parser/presentation/fields.py              |   31 +-
 aria/parser/presentation/null.py                |    4 +-
 aria/parser/presentation/presentation.py        |   54 +-
 aria/parser/presentation/source.py              |    2 +-
 aria/parser/presentation/utils.py               |   12 +-
 aria/parser/reading/__init__.py                 |   23 +
 aria/parser/reading/context.py                  |    8 +-
 aria/parser/reading/locator.py                  |    4 +-
 aria/parser/reading/reader.py                   |    2 +-
 aria/parser/specification.py                    |    4 +
 aria/parser/validation/__init__.py              |    4 +
 aria/parser/validation/context.py               |   15 +-
 aria/storage/__init__.py                        |   24 +-
 aria/storage/api.py                             |   78 +-
 aria/storage/collection_instrumentation.py      |   50 +-
 aria/storage/core.py                            |   62 +-
 aria/storage/exceptions.py                      |    4 +-
 aria/storage/filesystem_rapi.py                 |   53 +-
 aria/storage/sql_mapi.py                        |  162 +-
 aria/utils/__init__.py                          |    4 +
 aria/utils/archive.py                           |    3 +
 aria/utils/argparse.py                          |    6 +-
 aria/utils/caching.py                           |    9 +-
 aria/utils/collections.py                       |   34 +-
 aria/utils/console.py                           |    4 +
 aria/utils/exceptions.py                        |    4 +
 aria/utils/file.py                              |    9 +-
 aria/utils/formatting.py                        |   33 +-
 aria/utils/http.py                              |   24 +-
 aria/utils/imports.py                           |   12 +-
 aria/utils/openclose.py                         |    6 +-
 aria/utils/plugin.py                            |    4 +
 aria/utils/process.py                           |    4 +
 aria/utils/specification.py                     |    4 +
 aria/utils/threading.py                         |   52 +-
 aria/utils/type.py                              |   16 +-
 aria/utils/uris.py                              |    8 +-
 aria/utils/uuid.py                              |   20 +-
 aria/utils/validation.py                        |    6 +-
 aria/utils/versions.py                          |   13 +-
 docs/aria.cli.rst                               |  100 ++
 docs/aria.modeling.models.rst                   |   21 +
 docs/aria.modeling.rst                          |   56 +
 docs/aria.orchestrator.context.rst              |   46 +
 ....orchestrator.execution_plugin.ctx_proxy.rst |   31 +
 docs/aria.orchestrator.execution_plugin.rst     |   56 +
 docs/aria.orchestrator.execution_plugin.ssh.rst |   31 +
 docs/aria.orchestrator.rst                      |   46 +
 docs/aria.orchestrator.workflows.api.rst        |   31 +
 docs/aria.orchestrator.workflows.builtin.rst    |   57 +
 docs/aria.orchestrator.workflows.executor.rst   |   46 +
 docs/aria.orchestrator.workflows.rst            |   51 +
 docs/aria.parser.consumption.rst                |   21 +
 docs/aria.parser.loading.rst                    |   21 +
 docs/aria.parser.modeling.rst                   |   21 +
 docs/aria.parser.presentation.rst               |   21 +
 docs/aria.parser.reading.rst                    |   21 +
 docs/aria.parser.rst                            |   31 +
 docs/aria.parser.validation.rst                 |   21 +
 docs/aria.rst                                   |   40 +
 docs/aria.storage.rst                           |   51 +
 docs/aria.utils.rst                             |  121 ++
 docs/aria_extension_tosca.simple_nfv_v1_0.rst   |   20 +
 ...ria_extension_tosca.simple_v1_0.modeling.rst |   75 +
 ...extension_tosca.simple_v1_0.presentation.rst |   40 +
 docs/aria_extension_tosca.simple_v1_0.rst       |   20 +
 docs/cli.rst                                    |   57 +
 docs/conf.py                                    |   86 +-
 docs/index.rst                                  |   66 +-
 docs/parser.rst                                 |   56 -
 docs/requirements.txt                           |    3 +-
 docs/rest.rst                                   |   20 +
 docs/tosca.rst                                  |   36 -
 .../simple_nfv_v1_0/presenter.py                |    8 +-
 .../simple_v1_0/__init__.py                     |  109 ++
 .../simple_v1_0/assignments.py                  |   44 +-
 .../simple_v1_0/definitions.py                  |   79 +-
 .../aria_extension_tosca/simple_v1_0/filters.py |    8 +-
 .../aria_extension_tosca/simple_v1_0/misc.py    |   56 +-
 .../simple_v1_0/modeling/__init__.py            |    2 -
 .../simple_v1_0/modeling/capabilities.py        |    4 +-
 .../simple_v1_0/modeling/copy.py                |    2 +-
 .../simple_v1_0/modeling/data_types.py          |   10 +-
 .../simple_v1_0/modeling/functions.py           |   18 +-
 .../simple_v1_0/presentation/extensible.py      |    2 +-
 .../presentation/field_validators.py            |   40 +-
 .../simple_v1_0/presentation/types.py           |   12 +-
 .../simple_v1_0/presenter.py                    |    4 +-
 .../simple_v1_0/templates.py                    |   96 +-
 .../aria_extension_tosca/simple_v1_0/types.py   |   98 +-
 .../orchestrator/workflows/core/test_events.py  |    4 +-
 203 files changed, 6187 insertions(+), 3050 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/__init__.py
----------------------------------------------------------------------
diff --git a/aria/__init__.py b/aria/__init__.py
index bed1dc6..76a62ce 100644
--- a/aria/__init__.py
+++ b/aria/__init__.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-ARIA top level package
+The ARIA root package provides entry points for extension and storage initialization.
 """
 
 import sys
@@ -45,13 +45,17 @@ __all__ = (
     '__version__',
     'workflow',
     'operation',
+    'install_aria_extensions',
+    'application_model_storage',
+    'application_resource_storage'
 )
 
 
 def install_aria_extensions():
     """
-    Iterates all Python packages with names beginning with :code:`aria_extension_` and all
-    :code:`aria_extension` entry points and loads them.
+    Iterates all Python packages with names beginning with ``aria_extension_`` and all
+    ``aria_extension`` entry points and loads them.
+
     It then invokes all registered extension functions.
     """
     for loader, module_name, _ in iter_modules():
@@ -64,7 +68,7 @@ def install_aria_extensions():
 
 def application_model_storage(api, api_kwargs=None, initiator=None, initiator_kwargs=None):
     """
-    Initiate model storage
+    Initiate model storage.
     """
     return storage.ModelStorage(api_cls=api,
                                 api_kwargs=api_kwargs,
@@ -75,7 +79,7 @@ def application_model_storage(api, api_kwargs=None, initiator=None, initiator_kw
 
 def application_resource_storage(api, api_kwargs=None, initiator=None, initiator_kwargs=None):
     """
-    Initiate resource storage
+    Initiate resource storage.
     """
 
     return storage.ResourceStorage(api_cls=api,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/__init__.py
----------------------------------------------------------------------
diff --git a/aria/cli/__init__.py b/aria/cli/__init__.py
index ae1e83e..c0ef46f 100644
--- a/aria/cli/__init__.py
+++ b/aria/cli/__init__.py
@@ -12,3 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+CLI package.
+"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/color.py
----------------------------------------------------------------------
diff --git a/aria/cli/color.py b/aria/cli/color.py
index 5e0355a..03381ba 100644
--- a/aria/cli/color.py
+++ b/aria/cli/color.py
@@ -12,6 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+Terminal colorization utilities.
+"""
+
 from StringIO import StringIO
 import re
 
@@ -75,8 +80,7 @@ class ColorSpec(object):
     def __init__(self, fore=None, back=None, style=None):
         """
         It is possible to provide fore, back and style arguments. each could be either
-        the color is lower case letter, or the actual color from colorama.
-
+        the color is lower case letter, or the actual color from Colorama.
         """
         self._kwargs = dict(fore=fore, back=back, style=style)
         self._str = StringIO()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/__init__.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/__init__.py b/aria/cli/commands/__init__.py
index a01a029..ba34a43 100644
--- a/aria/cli/commands/__init__.py
+++ b/aria/cli/commands/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI commands package.
+"""
+
 from . import (
     executions,
     logs,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/executions.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/executions.py b/aria/cli/commands/executions.py
index 9f56ccd..ea70af5 100644
--- a/aria/cli/commands/executions.py
+++ b/aria/cli/commands/executions.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``executions`` sub-commands.
+"""
+
 import os
 
 from .. import helptexts
@@ -27,28 +31,30 @@ from ...orchestrator.workflows.executor.dry import DryExecutor
 from ...utils import formatting
 from ...utils import threading
 
-EXECUTION_COLUMNS = ['id', 'workflow_name', 'status', 'service_name',
-                     'created_at', 'error']
+EXECUTION_COLUMNS = ('id', 'workflow_name', 'status', 'service_name',
+                     'created_at', 'error')
 
 
 @aria.group(name='executions')
 @aria.options.verbose()
 def executions():
-    """Handle workflow executions
+    """
+    Manage executions
     """
     pass
 
 
 @executions.command(name='show',
-                    short_help='Show execution information')
+                    short_help='Show information for an execution')
 @aria.argument('execution-id')
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def show(execution_id, model_storage, logger):
-    """Show information for a specific execution
+    """
+    Show information for an execution
 
-    `EXECUTION_ID` is the execution to get information on.
+    EXECUTION_ID is the unique ID of the execution.
     """
     logger.info('Showing execution {0}'.format(execution_id))
     execution = model_storage.execution.get(execution_id)
@@ -68,7 +74,7 @@ def show(execution_id, model_storage, logger):
 
 
 @executions.command(name='list',
-                    short_help='List service executions')
+                    short_help='List executions')
 @aria.options.service_name(required=False)
 @aria.options.sort_by()
 @aria.options.descending
@@ -80,10 +86,11 @@ def list(service_name,
          descending,
          model_storage,
          logger):
-    """List executions
+    """
+    List executions
 
-    If `SERVICE_NAME` is provided, list executions for that service.
-    Otherwise, list executions for all services.
+    If SERVICE_NAME is provided, list executions on that service. Otherwise, list executions on all
+    services.
     """
     if service_name:
         logger.info('Listing executions for service {0}...'.format(
@@ -102,7 +109,7 @@ def list(service_name,
 
 
 @executions.command(name='start',
-                    short_help='Execute a workflow')
+                    short_help='Start a workflow on a service')
 @aria.argument('workflow-name')
 @aria.options.service_name(required=True)
 @aria.options.inputs(help=helptexts.EXECUTION_INPUTS)
@@ -126,9 +133,12 @@ def start(workflow_name,
           resource_storage,
           plugin_manager,
           logger):
-    """Execute a workflow
+    """
+    Start a workflow on a service
 
-    `WORKFLOW_NAME` is the name of the workflow to execute (e.g. `uninstall`)
+    SERVICE_NAME is the unique name of the service.
+
+    WORKFLOW_NAME is the unique name of the workflow within the service (e.g. "uninstall").
     """
     service = model_storage.service.get_by_name(service_name)
     executor = DryExecutor() if dry else None  # use WorkflowRunner's default executor
@@ -145,7 +155,7 @@ def start(workflow_name,
 
 
 @executions.command(name='resume',
-                    short_help='Resume a workflow')
+                    short_help='Resume a stopped execution')
 @aria.argument('execution-id')
 @aria.options.inputs(help=helptexts.EXECUTION_INPUTS)
 @aria.options.dry_execution
@@ -166,6 +176,11 @@ def resume(execution_id,
            resource_storage,
            plugin_manager,
            logger):
+    """
+    Resume a stopped execution
+
+    EXECUTION_ID is the unique ID of the execution.
+    """
     executor = DryExecutor() if dry else None  # use WorkflowRunner's default executor
 
     execution = model_storage.execution.get(execution_id)
@@ -225,7 +240,7 @@ def _run_execution(workflow_runner, logger, model_storage, dry, mark_pattern):
 
 
 def _cancel_execution(workflow_runner, execution_thread, logger, log_iterator):
-    logger.info('Cancelling execution. Press Ctrl+C again to force-cancel')
+    logger.info('Cancelling execution. Press Ctrl+C again to force-cancel.')
     workflow_runner.cancel()
     while execution_thread.is_alive():
         try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/logs.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/logs.py b/aria/cli/commands/logs.py
index 2f7f361..b751b97 100644
--- a/aria/cli/commands/logs.py
+++ b/aria/cli/commands/logs.py
@@ -12,6 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+CLI ``logs`` sub-commands.
+"""
+
 from .. import execution_logging
 from ..logger import ModelLogIterator
 from ..core import aria
@@ -20,20 +25,24 @@ from ..core import aria
 @aria.group(name='logs')
 @aria.options.verbose()
 def logs():
-    """Show logs from workflow executions
+    """
+    Manage logs of workflow executions
     """
     pass
 
 
 @logs.command(name='list',
-              short_help='List execution logs')
+              short_help='List logs for an execution')
 @aria.argument('execution-id')
 @aria.options.verbose()
 @aria.options.mark_pattern()
 @aria.pass_model_storage
 @aria.pass_logger
 def list(execution_id, mark_pattern, model_storage, logger):
-    """Display logs for an execution
+    """
+    List logs for an execution
+
+    EXECUTION_ID is the unique ID of the execution.
     """
     logger.info('Listing logs for execution id {0}'.format(execution_id))
     log_iterator = ModelLogIterator(model_storage, execution_id)
@@ -45,15 +54,16 @@ def list(execution_id, mark_pattern, model_storage, logger):
 
 
 @logs.command(name='delete',
-              short_help='Delete execution logs')
+              short_help='Delete logs of an execution')
 @aria.argument('execution-id')
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def delete(execution_id, model_storage, logger):
-    """Delete logs of an execution
+    """
+    Delete logs of an execution
 
-    `EXECUTION_ID` is the execution logs to delete.
+    EXECUTION_ID is the unique ID of the execution.
     """
     logger.info('Deleting logs for execution id {0}'.format(execution_id))
     logs_list = model_storage.log.list(filters=dict(execution_fk=execution_id))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/node_templates.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/node_templates.py b/aria/cli/commands/node_templates.py
index 50c755e..ec160d2 100644
--- a/aria/cli/commands/node_templates.py
+++ b/aria/cli/commands/node_templates.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``node-templates`` sub-commands.
+"""
+
 from .. import table
 from .. import utils
 from ..core import aria
@@ -24,22 +28,24 @@ NODE_TEMPLATE_COLUMNS = ['id', 'name', 'description', 'service_template_name', '
 @aria.group(name='node-templates')
 @aria.options.verbose()
 def node_templates():
-    """Handle a service template's node templates
+    """
+    Manages stored service templates' node templates
     """
     pass
 
 
 @node_templates.command(name='show',
-                        short_help='Show node information')
+                        short_help='Show information for a stored node template')
 @aria.argument('node-template-id')
 # @aria.options.service_template_name(required=True)
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def show(node_template_id, model_storage, logger):
-    """Show information for a specific node of a specific service template
+    """
+    Show information for a stored node template
 
-    `NODE_TEMPLATE_ID` is the node id to get information on.
+    NODE_TEMPLATE_ID is the unique node template ID.
     """
     logger.info('Showing node template {0}'.format(node_template_id))
     node_template = model_storage.node_template.get(node_template_id)
@@ -64,7 +70,7 @@ def show(node_template_id, model_storage, logger):
 
 
 @node_templates.command(name='list',
-                        short_help='List node templates for a service template')
+                        short_help='List stored node templates')
 @aria.options.service_template_name()
 @aria.options.sort_by('service_template_name')
 @aria.options.descending
@@ -72,9 +78,10 @@ def show(node_template_id, model_storage, logger):
 @aria.pass_model_storage
 @aria.pass_logger
 def list(service_template_name, sort_by, descending, model_storage, logger):
-    """List node templates
+    """
+    List stored node templates
 
-    If `SERVICE_TEMPLATE_NAME` is provided, list nodes for that service template.
+    If SERVICE_TEMPLATE_NAME is provided, list node templates for that stored service template.
     Otherwise, list node templates for all service templates.
     """
     if service_template_name:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/nodes.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/nodes.py b/aria/cli/commands/nodes.py
index 1bbefe6..30f1dd4 100644
--- a/aria/cli/commands/nodes.py
+++ b/aria/cli/commands/nodes.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``nodes`` sub-commands.
+"""
+
 from .. import table
 from .. import utils
 from ..core import aria
@@ -24,21 +28,23 @@ NODE_COLUMNS = ['id', 'name', 'service_name', 'node_template_name', 'state']
 @aria.group(name='nodes')
 @aria.options.verbose()
 def nodes():
-    """Handle a service's nodes
+    """
+    Manage services' nodes
     """
     pass
 
 
 @nodes.command(name='show',
-               short_help='Show node information')
+               short_help='Show information for a node')
 @aria.argument('node_id')
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def show(node_id, model_storage, logger):
-    """Showing information for a specific node
+    """
+    Show information for a node
 
-    `NODE_ID` is the id of the node to get information on.
+    NODE_ID is the unique node ID.
     """
     logger.info('Showing node {0}'.format(node_id))
     node = model_storage.node.get(node_id)
@@ -55,7 +61,7 @@ def show(node_id, model_storage, logger):
 
 
 @nodes.command(name='list',
-               short_help='List node for a service')
+               short_help='List node')
 @aria.options.service_name(required=False)
 @aria.options.sort_by('service_name')
 @aria.options.descending
@@ -67,10 +73,11 @@ def list(service_name,
          descending,
          model_storage,
          logger):
-    """List nodes
+    """
+    List nodes
 
-    If `SERVICE_NAME` is provided, list nodes for that service.
-    Otherwise, list nodes for all services.
+    If SERVICE_NAME is provided, list nodes for that service. Otherwise, list nodes for all
+    services.
     """
     if service_name:
         logger.info('Listing nodes for service {0}...'.format(service_name))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/plugins.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/plugins.py b/aria/cli/commands/plugins.py
index 670288e..b5d68a2 100644
--- a/aria/cli/commands/plugins.py
+++ b/aria/cli/commands/plugins.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``plugins`` sub-commands.
+"""
+
 from .. import table
 from .. import utils
 from ..core import aria
@@ -25,24 +29,26 @@ PLUGIN_COLUMNS = ['id', 'package_name', 'package_version', 'supported_platform',
 @aria.group(name='plugins')
 @aria.options.verbose()
 def plugins():
-    """Handle plugins
+    """
+    Manage plugins
     """
     pass
 
 
 @plugins.command(name='validate',
-                 short_help='Validate a plugin')
+                 short_help='Validate a plugin archive')
 @aria.argument('plugin-path')
 @aria.options.verbose()
 @aria.pass_plugin_manager
 @aria.pass_logger
 def validate(plugin_path, plugin_manager, logger):
-    """Validate a plugin archive
+    """
+    Validate a plugin archive
 
-    A valid plugin is a wagon (http://github.com/cloudify-cosmo/wagon)
-    in the zip format (suffix may also be .wgn).
+    A valid plugin is a wagon (`http://github.com/cloudify-cosmo/wagon`) in the ZIP format (suffix
+    may also be `.wgn`).
 
-    `PLUGIN_PATH` is the path to wagon archive to validate.
+    PLUGIN_PATH is the path to the wagon archive.
     """
     logger.info('Validating plugin {0}...'.format(plugin_path))
     plugin_manager.validate_plugin(plugin_path)
@@ -57,9 +63,13 @@ def validate(plugin_path, plugin_manager, logger):
 @aria.pass_plugin_manager
 @aria.pass_logger
 def install(ctx, plugin_path, plugin_manager, logger):
-    """Install a plugin
+    """
+    Install a plugin
 
-    `PLUGIN_PATH` is the path to wagon archive to install.
+    A valid plugin is a wagon (`http://github.com/cloudify-cosmo/wagon`) in the ZIP format (suffix
+    may also be `.wgn`).
+
+    PLUGIN_PATH is the path to the wagon archive.
     """
     ctx.invoke(validate, plugin_path=plugin_path)
     logger.info('Installing plugin {0}...'.format(plugin_path))
@@ -68,15 +78,16 @@ def install(ctx, plugin_path, plugin_manager, logger):
 
 
 @plugins.command(name='show',
-                 short_help='show plugin information')
+                 short_help='Show information for an installed plugin')
 @aria.argument('plugin-id')
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def show(plugin_id, model_storage, logger):
-    """Show information for a specific plugin
+    """
+    Show information for an installed plugin
 
-    `PLUGIN_ID` is the id of the plugin to show information on.
+    PLUGIN_ID is the unique installed plugin ID in this ARIA instance.
     """
     logger.info('Showing plugin {0}...'.format(plugin_id))
     plugin = model_storage.plugin.get(plugin_id)
@@ -84,14 +95,15 @@ def show(plugin_id, model_storage, logger):
 
 
 @plugins.command(name='list',
-                 short_help='List plugins')
+                 short_help='List all installed plugins')
 @aria.options.sort_by('uploaded_at')
 @aria.options.descending
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def list(sort_by, descending, model_storage, logger):
-    """List all plugins on the manager
+    """
+    List all installed plugins
     """
     logger.info('Listing all plugins...')
     plugins_list = model_storage.plugin.list(

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/reset.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/reset.py b/aria/cli/commands/reset.py
index 1fe0714..c82c707 100644
--- a/aria/cli/commands/reset.py
+++ b/aria/cli/commands/reset.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``reset`` command.
+"""
+
 from .. import helptexts
 from ..core import aria
 from ..env import env
@@ -20,7 +24,7 @@ from ..exceptions import AriaCliError
 
 
 @aria.command(name='reset',
-              short_help="Reset ARIA's working directory")
+              short_help="Reset ARIA working directory")
 @aria.options.force(help=helptexts.FORCE_RESET)
 @aria.options.reset_config
 @aria.pass_logger
@@ -28,9 +32,10 @@ from ..exceptions import AriaCliError
 def reset(force, reset_config, logger):
     """
     Reset ARIA working directory
-    Resetting the working directory will result in the deletion of all state in ARIA; The user
-     configuration will remain intact, unless the `reset_config` flag has been set as well, in
-     which case the entire ARIA working directory shall be removed.
+
+    Deletes installed plugins, service templates, services, executions, and logs. The user
+    configuration will remain intact unless the `--reset_config` flag has been set as well, in
+    which case the entire ARIA working directory shall be removed.
     """
     if not force:
         raise AriaCliError("To reset the ARIA's working directory, you must also provide the force"

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/service_templates.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/service_templates.py b/aria/cli/commands/service_templates.py
index d139195..f567aa8 100644
--- a/aria/cli/commands/service_templates.py
+++ b/aria/cli/commands/service_templates.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``service-templates`` sub-commands.
+"""
 
 import os
 
@@ -35,13 +38,14 @@ SERVICE_TEMPLATE_COLUMNS = \
 @aria.group(name='service-templates')
 @aria.options.verbose()
 def service_templates():
-    """Handle service templates on the manager
+    """
+    Manage service templates
     """
     pass
 
 
 @service_templates.command(name='show',
-                           short_help='Show service template information')
+                           short_help='Show information for a stored service template')
 @aria.argument('service-template-name')
 @aria.options.verbose()
 @aria.pass_model_storage
@@ -52,9 +56,10 @@ def service_templates():
 @aria.pass_logger
 def show(service_template_name, model_storage, mode_full, mode_types, format_json, format_yaml,
          logger):
-    """Show information for a specific service template
+    """
+    Show information for a stored service template
 
-    `SERVICE_TEMPLATE_NAME` is the name of the service template to show information on.
+    SERVICE_TEMPLATE_NAME is the unique name of the stored service template.
     """
     service_template = model_storage.service_template.get_by_name(service_template_name)
 
@@ -94,14 +99,15 @@ def show(service_template_name, model_storage, mode_full, mode_types, format_jso
 
 
 @service_templates.command(name='list',
-                           short_help='List service templates')
+                           short_help='List all stored service templates')
 @aria.options.sort_by()
 @aria.options.descending
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def list(sort_by, descending, model_storage, logger):
-    """List all service templates
+    """
+    List all stored service templates
     """
 
     logger.info('Listing all service templates...')
@@ -115,7 +121,7 @@ def list(sort_by, descending, model_storage, logger):
 
 
 @service_templates.command(name='store',
-                           short_help='Store a service template')
+                           short_help='Parse and store a service template archive')
 @aria.argument('service-template-path')
 @aria.argument('service-template-name')
 @aria.options.service_template_filename
@@ -126,11 +132,12 @@ def list(sort_by, descending, model_storage, logger):
 @aria.pass_logger
 def store(service_template_path, service_template_name, service_template_filename,
           model_storage, resource_storage, plugin_manager, logger):
-    """Store a service template
+    """
+    Parse and store a service template archive
 
-    `SERVICE_TEMPLATE_PATH` is the path of the service template to store.
+    SERVICE_TEMPLATE_PATH is the path to the service template archive.
 
-    `SERVICE_TEMPLATE_NAME` is the name of the service template to store.
+    SERVICE_TEMPLATE_NAME is the unique name to give to the service template in storage.
     """
     logger.info('Storing service template {0}...'.format(service_template_name))
 
@@ -148,7 +155,7 @@ def store(service_template_path, service_template_name, service_template_filenam
 
 
 @service_templates.command(name='delete',
-                           short_help='Delete a service template')
+                           short_help='Delete a stored service template')
 @aria.argument('service-template-name')
 @aria.options.verbose()
 @aria.pass_model_storage
@@ -156,9 +163,10 @@ def store(service_template_path, service_template_name, service_template_filenam
 @aria.pass_plugin_manager
 @aria.pass_logger
 def delete(service_template_name, model_storage, resource_storage, plugin_manager, logger):
-    """Delete a service template
+    """
+    Delete a stored service template
 
-    `SERVICE_TEMPLATE_NAME` is the name of the service template to delete.
+    SERVICE_TEMPLATE_NAME is the unique name of the stored service template.
     """
     logger.info('Deleting service template {0}...'.format(service_template_name))
     service_template = model_storage.service_template.get_by_name(service_template_name)
@@ -168,22 +176,23 @@ def delete(service_template_name, model_storage, resource_storage, plugin_manage
 
 
 @service_templates.command(name='inputs',
-                           short_help='Show service template inputs')
+                           short_help='Show stored service template inputs')
 @aria.argument('service-template-name')
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def inputs(service_template_name, model_storage, logger):
-    """Show inputs for a specific service template
+    """
+    Show stored service template inputs
 
-    `SERVICE_TEMPLATE_NAME` is the name of the service template to show inputs for.
+    SERVICE_TEMPLATE_NAME is the unique name of the stored service template.
     """
     logger.info('Showing inputs for service template {0}...'.format(service_template_name))
     print_service_template_inputs(model_storage, service_template_name, logger)
 
 
 @service_templates.command(name='validate',
-                           short_help='Validate a service template')
+                           short_help='Validate a service template archive')
 @aria.argument('service-template')
 @aria.options.service_template_filename
 @aria.options.verbose()
@@ -193,9 +202,10 @@ def inputs(service_template_name, model_storage, logger):
 @aria.pass_logger
 def validate(service_template, service_template_filename,
              model_storage, resource_storage, plugin_manager, logger):
-    """Validate a service template
+    """
+    Validate a service template archive
 
-    `SERVICE_TEMPLATE` is the path or URL of the service template or archive to validate.
+    SERVICE_TEMPLATE_PATH is the path to the service template archive.
     """
     logger.info('Validating service template: {0}'.format(service_template))
     service_template_path = service_template_utils.get(service_template, service_template_filename)
@@ -205,16 +215,18 @@ def validate(service_template, service_template_filename,
 
 
 @service_templates.command(name='create-archive',
-                           short_help='Create a CSAR archive')
+                           short_help='Create a CSAR archive from a service template source')
 @aria.argument('service-template-path')
 @aria.argument('destination')
 @aria.options.verbose()
 @aria.pass_logger
 def create_archive(service_template_path, destination, logger):
-    """Create a CSAR archive
+    """
+    Create a CSAR archive from a service template source
+
+    SERVICE_TEMPLATE_PATH is the path to the service template source.
 
-    `service_template_path` is the path of the service template to create the archive from
-    `destination` is the path of the output CSAR archive
+    DESTINATION is the path to the created CSAR archive.
     """
     logger.info('Creating a CSAR archive')
     if not destination.endswith(csar.CSAR_FILE_EXTENSION):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/services.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/services.py b/aria/cli/commands/services.py
index ae5895a..a99f5b3 100644
--- a/aria/cli/commands/services.py
+++ b/aria/cli/commands/services.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``services`` sub-commands.
+"""
 
 import os
 from StringIO import StringIO
@@ -36,13 +39,14 @@ SERVICE_COLUMNS = ('id', 'name', 'description', 'service_template_name', 'create
 @aria.group(name='services')
 @aria.options.verbose()
 def services():
-    """Handle services
+    """
+    Manage services
     """
     pass
 
 
 @services.command(name='show',
-                  short_help='Display service information')
+                  short_help='Show information for a service')
 @aria.argument('service-name')
 @aria.options.verbose()
 @aria.options.service_mode_full
@@ -52,9 +56,10 @@ def services():
 @aria.pass_model_storage
 @aria.pass_logger
 def show(service_name, model_storage, mode_full, mode_graph, format_json, format_yaml, logger):
-    """Show information for a specific service template
+    """
+    Show information for a service
 
-    `SERVICE_NAME` is the name of the service to display information on.
+    SERVICE_NAME is the unique name of the service.
     """
     service = model_storage.service.get_by_name(service_name)
 
@@ -99,10 +104,11 @@ def list(service_template_name,
          descending,
          model_storage,
          logger):
-    """List services
+    """
+    List services
 
-    If `--service-template-name` is provided, list services for that service template.
-    Otherwise, list services for all service templates.
+    If `--service-template-name` is provided, list services based on that service template.
+    Otherwise, list all services.
     """
     if service_template_name:
         logger.info('Listing services for service template {0}...'.format(
@@ -120,7 +126,7 @@ def list(service_template_name,
 
 
 @services.command(name='create',
-                  short_help='Create a services')
+                  short_help='Create a service')
 @aria.argument('service-name', required=False)
 @aria.options.service_template_name(required=True)
 @aria.options.inputs(help=helptexts.SERVICE_INPUTS)
@@ -136,10 +142,10 @@ def create(service_template_name,
            resource_storage,
            plugin_manager,
            logger):
-    """Create a service
-
-    `SERVICE_NAME` is the name of the service you'd like to create.
+    """
+    Create a service
 
+    SERVICE_NAME is the unique name to give to the service.
     """
     logger.info('Creating new service from service template {0}...'.format(
         service_template_name))
@@ -168,9 +174,10 @@ def create(service_template_name,
 @aria.pass_plugin_manager
 @aria.pass_logger
 def delete(service_name, force, model_storage, resource_storage, plugin_manager, logger):
-    """Delete a service
+    """
+    Delete a service
 
-    `SERVICE_NAME` is the name of the service to delete.
+    SERVICE_NAME is the unique name of the service.
     """
     logger.info('Deleting service {0}...'.format(service_name))
     service = model_storage.service.get_by_name(service_name)
@@ -186,9 +193,10 @@ def delete(service_name, force, model_storage, resource_storage, plugin_manager,
 @aria.pass_model_storage
 @aria.pass_logger
 def outputs(service_name, model_storage, logger):
-    """Show outputs for a specific service
+    """
+    Show service outputs
 
-    `SERVICE_NAME` is the name of the service to print outputs for.
+    SERVICE_NAME is the unique name of the service.
     """
     logger.info('Showing outputs for service {0}...'.format(service_name))
     service = model_storage.service.get_by_name(service_name)
@@ -211,9 +219,10 @@ def outputs(service_name, model_storage, logger):
 @aria.pass_model_storage
 @aria.pass_logger
 def inputs(service_name, model_storage, logger):
-    """Show inputs for a specific service
+    """
+    Show service inputs
 
-    `SERVICE_NAME` is the id of the service to print inputs for.
+    SERVICE_NAME is the unique name of the service.
     """
     logger.info('Showing inputs for service {0}...'.format(service_name))
     service = model_storage.service.get_by_name(service_name)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/commands/workflows.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/workflows.py b/aria/cli/commands/workflows.py
index 221dbc4..03cf00e 100644
--- a/aria/cli/commands/workflows.py
+++ b/aria/cli/commands/workflows.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI ``worfklows`` sub-commands.
+"""
+
 from .. import table
 from ..core import aria
 from ..exceptions import AriaCliError
@@ -22,22 +26,26 @@ WORKFLOW_COLUMNS = ['name', 'service_template_name', 'service_name']
 
 @aria.group(name='workflows')
 def workflows():
-    """Handle service workflows
+    """
+    Manage service workflows
     """
     pass
 
 
 @workflows.command(name='show',
-                   short_help='Show workflow information')
+                   short_help='Show information for a service workflow')
 @aria.argument('workflow-name')
 @aria.options.service_name(required=True)
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def show(workflow_name, service_name, model_storage, logger):
-    """Show information for a specific workflow of a specific service
+    """
+    Show information for a service workflow
 
-    `WORKFLOW_NAME` is the name of the workflow to get information on.
+    SERVICE_NAME is the unique name of the service.
+
+    WORKFLOW_NAME is the unique name of the workflow within the service (e.g. "uninstall").
     """
     logger.info('Retrieving workflow {0} for service {1}'.format(
         workflow_name, service_name))
@@ -81,13 +89,16 @@ def show(workflow_name, service_name, model_storage, logger):
 
 
 @workflows.command(name='list',
-                   short_help='List workflows for a service')
+                   short_help='List service workflows')
 @aria.options.service_name(required=True)
 @aria.options.verbose()
 @aria.pass_model_storage
 @aria.pass_logger
 def list(service_name, model_storage, logger):
-    """List all workflows of a specific service
+    """
+    List service workflows
+
+    SERVICE_NAME is the unique name of the service.
     """
     logger.info('Listing workflows for service {0}...'.format(service_name))
     service = model_storage.service.get_by_name(service_name)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/config/__init__.py
----------------------------------------------------------------------
diff --git a/aria/cli/config/__init__.py b/aria/cli/config/__init__.py
index ae1e83e..738e8ed 100644
--- a/aria/cli/config/__init__.py
+++ b/aria/cli/config/__init__.py
@@ -12,3 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+CLI configuration package.
+"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/config/config.py
----------------------------------------------------------------------
diff --git a/aria/cli/config/config.py b/aria/cli/config/config.py
index d584fad..bbece80 100644
--- a/aria/cli/config/config.py
+++ b/aria/cli/config/config.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI configuration mechanism.
+"""
 
 import os
 import pkg_resources

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/core/__init__.py
----------------------------------------------------------------------
diff --git a/aria/cli/core/__init__.py b/aria/cli/core/__init__.py
index ae1e83e..88a9801 100644
--- a/aria/cli/core/__init__.py
+++ b/aria/cli/core/__init__.py
@@ -12,3 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+CLI core package.
+"""

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/core/aria.py
----------------------------------------------------------------------
diff --git a/aria/cli/core/aria.py b/aria/cli/core/aria.py
index e5b3eb2..515c06a 100644
--- a/aria/cli/core/aria.py
+++ b/aria/cli/core/aria.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Enhancements and ARIA-specific conveniences for `Click <http://click.pocoo.org>`__.
+"""
+
 import os
 import sys
 import difflib
@@ -227,9 +231,8 @@ class AliasedGroup(click.Group):
 
     def resolve_command(self, ctx, args):
         """
-        Override clicks ``resolve_command`` method
-        and appends *Did you mean ...* suggestions
-        to the raised exception message.
+        Override clicks ``resolve_command`` method and appends *Did you mean ...* suggestions to the
+        raised exception message.
         """
         try:
             return super(AliasedGroup, self).resolve_command(ctx, args)
@@ -250,7 +253,7 @@ class AliasedGroup(click.Group):
 
 def group(name):
     """
-    Allow to create a group with a default click context and a cls for click's ``didyoueamn``
+    Allow to create a group with a default click context and a class for Click's ``didyoueamn``
     without having to repeat it for every group.
     """
     return click.group(
@@ -271,7 +274,7 @@ def command(*args, **kwargs):
 
 def argument(*args, **kwargs):
     """
-    Make Click arguments ARIA specific.
+    Make Click arguments specific to ARIA.
 
     This exists purely for aesthetic reasons, otherwise some decorators are called
     ``@click.something`` instead of ``@aria.something``

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/csar.py
----------------------------------------------------------------------
diff --git a/aria/cli/csar.py b/aria/cli/csar.py
index 8f44557..40b1699 100644
--- a/aria/cli/csar.py
+++ b/aria/cli/csar.py
@@ -13,6 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Support for the CSAR (Cloud Service ARchive) packaging specification.
+
+See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc461787381>`__
+"""
+
 import os
 import logging
 import pprint

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/defaults.py
----------------------------------------------------------------------
diff --git a/aria/cli/defaults.py b/aria/cli/defaults.py
index 5c16938..e84abc0 100644
--- a/aria/cli/defaults.py
+++ b/aria/cli/defaults.py
@@ -13,8 +13,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Various CLI default values.
+"""
 
+#: Default service template filename
 SERVICE_TEMPLATE_FILENAME = 'service_template.yaml'
+
+#: Default task max attempts
 TASK_MAX_ATTEMPTS = 30
+
+#: Default task retry interval
 TASK_RETRY_INTERVAL = 30
+
+#: Default sort descending
 SORT_DESCENDING = False

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/env.py
----------------------------------------------------------------------
diff --git a/aria/cli/env.py b/aria/cli/env.py
index 52a4ec6..84bdebe 100644
--- a/aria/cli/env.py
+++ b/aria/cli/env.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Environment (private)
+"""
 
 import os
 import shutil

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/cli/exceptions.py b/aria/cli/exceptions.py
index 89cfacd..7da9836 100644
--- a/aria/cli/exceptions.py
+++ b/aria/cli/exceptions.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+CLI exceptions.
+"""
 
 from ..exceptions import AriaError
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/execution_logging.py
----------------------------------------------------------------------
diff --git a/aria/cli/execution_logging.py b/aria/cli/execution_logging.py
index 248ff7c..af40e01 100644
--- a/aria/cli/execution_logging.py
+++ b/aria/cli/execution_logging.py
@@ -12,6 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+"""
+Formatting for ``executions`` sub-commands.
+"""
+
 import os
 import re
 from StringIO import StringIO

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/helptexts.py
----------------------------------------------------------------------
diff --git a/aria/cli/helptexts.py b/aria/cli/helptexts.py
index 74934db..a5d41e8 100644
--- a/aria/cli/helptexts.py
+++ b/aria/cli/helptexts.py
@@ -13,10 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Gathers all CLI command help texts in one place.
+"""
 
 DEFAULT_MUTUALITY_ERROR_MESSAGE = 'mutually exclusive'
 VERBOSE = \
-    "Show verbose output. You can supply this up to three times (i.e. -vvv)"
+    "Show verbose output; you can supply this up to three times (i.e. -vvv)"
 
 VERSION = "Display the version and exit"
 FORCE_RESET = "Confirmation for resetting ARIA's working directory"
@@ -28,12 +31,12 @@ EXECUTION_ID = "The unique identifier for the execution"
 
 SERVICE_TEMPLATE_PATH = "The path to the application's service template file"
 SERVICE_TEMPLATE_FILENAME = (
-    "The name of the archive's main service template file. "
-    "This is only relevant if uploading a (non-CSAR) archive")
+    "The name of the archive's main service template file "
+    "(only relevant if uploading a non-CSAR archive)")
 INPUTS_PARAMS_USAGE = (
-    '(Can be provided as wildcard based paths '
-    '(*.yaml, /my_inputs/, etc..) to YAML files, a JSON string or as '
-    'key1=value1;key2=value2). This argument can be used multiple times')
+    '(can be provided as wildcard based paths '
+    '("inp?.yaml", "/my_inputs/", etc.) to YAML files, a JSON string or as '
+    '"key1=value1;key2=value2"); this argument can be used multiple times')
 SERVICE_INPUTS = "Inputs for the service {0}".format(INPUTS_PARAMS_USAGE)
 EXECUTION_INPUTS = "Inputs for the execution {0}".format(INPUTS_PARAMS_USAGE)
 
@@ -46,8 +49,8 @@ DRY_EXECUTION = "Execute a workflow dry run (prints operations information witho
 IGNORE_AVAILABLE_NODES = "Delete the service even if it has available nodes"
 SORT_BY = "Key for sorting the list"
 DESCENDING = "Sort list in descending order [default: False]"
-JSON_OUTPUT = "Output logs in a consumable JSON format"
-MARK_PATTERN = "Mark a regex pattern in the logs"
+JSON_OUTPUT = "Output logs in JSON format"
+MARK_PATTERN = "Mark a regular expression pattern in the logs"
 
 SHOW_FULL = "Show full information"
 SHOW_JSON = "Show in JSON format (implies --full)"

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/inputs.py
----------------------------------------------------------------------
diff --git a/aria/cli/inputs.py b/aria/cli/inputs.py
index 4d46ebb..bea3e1a 100644
--- a/aria/cli/inputs.py
+++ b/aria/cli/inputs.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Helpers for validating and coercing service template inputs.
+"""
+
 import os
 import glob
 from ruamel import yaml
@@ -22,15 +26,17 @@ from .exceptions import AriaCliError
 
 
 def inputs_to_dict(resources):
-    """Returns a dictionary of inputs
-
-    `resources` can be:
-    - A list of files.
-    - A single file
-    - A directory containing multiple input files
-    - A key1=value1;key2=value2 pairs string.
-    - A string formatted as JSON/YAML.
-    - Wildcard based string (e.g. *-inputs.yaml)
+    """
+    Returns a dictionary of inputs
+
+    :param resources: can be:
+
+     * list of files
+     * single file
+     * directory containing multiple input files
+     * ``key1=value1;key2=value2`` pairs string.
+     * string formatted as JSON/YAML
+     * wildcard based string (e.g. ``*-inputs.yaml``)
     """
     if not resources:
         return dict()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/logger.py
----------------------------------------------------------------------
diff --git a/aria/cli/logger.py b/aria/cli/logger.py
index 96f3fb3..14baae0 100644
--- a/aria/cli/logger.py
+++ b/aria/cli/logger.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Centralized logging configuration and formatting.
+"""
 
 import os
 import copy

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/main.py
----------------------------------------------------------------------
diff --git a/aria/cli/main.py b/aria/cli/main.py
index 02cf095..640360b 100644
--- a/aria/cli/main.py
+++ b/aria/cli/main.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Executable entry point into the CLI.
+"""
+
 from aria import install_aria_extensions
 from aria.cli import commands
 from aria.cli.core import aria
@@ -22,12 +26,15 @@ from aria.cli.core import aria
 @aria.options.verbose()
 @aria.options.version
 def _aria():
-    """ARIA's Command Line Interface
+    """
+    ARIA's Command Line Interface.
+
+    To activate bash-completion run::
 
-    To activate bash-completion. Run: `eval "$(_ARIA_COMPLETE=source aria)"`
+        eval "$(_ARIA_COMPLETE=source aria)"
 
-    ARIA's working directory resides by default in ~/.aria. To change it, set
-    the environment variable `ARIA_WORKDIR` to something else (e.g. /tmp/).
+    ARIA's working directory resides by default in "~/.aria". To change it, set the environment
+    variable ARIA_WORKDIR to something else (e.g. "/tmp/").
     """
     aria.set_cli_except_hook()
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/service_template_utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/service_template_utils.py b/aria/cli/service_template_utils.py
index c953c02..5312522 100644
--- a/aria/cli/service_template_utils.py
+++ b/aria/cli/service_template_utils.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Loading mechanism for service templates.
+"""
+
 import os
 from urlparse import urlparse
 
@@ -23,26 +27,24 @@ from ..utils import archive as archive_utils
 
 
 def get(source, service_template_filename):
-    """Get a source and return a path to the main service template file
+    """
+    Get a source and return a path to the main service template file
 
     The behavior based on then source argument content is:
-        - local yaml file: return the file
-        - local archive:
-            extract it locally and return path service template file
-        - URL:
-            - download and get service template from downloaded archive
-        - github repo:
-            - download and get service template from downloaded archive
-
-    Supported archive types are: csar, zip, tar, tar.gz and tar.bz2
-
-    :param source: Path/URL/github repo to archive/service-template file
-    :type source: str
-    :param service_template_filename: Path to service template (if source is an archive [but
-     not a csar archive - with csars archives, this is read from the metadata file])
-    :type service_template_filename: str
-    :return: Path to main service template file
-    :rtype: str
+
+    * local ``.yaml`` file: return the file
+    * local archive (``.csar``, ``.zip``, ``.tar``, ``.tar.gz``, and ``.tar.bz2``): extract it
+      locally and return path service template file
+    * URL: download and get service template from downloaded archive
+    * GitHub repo: download and get service template from downloaded archive
+
+    :param source: path/URL/GitHub repo to archive/service-template file
+    :type source: basestring
+    :param service_template_filename: path to service template if source is a non-CSAR archive
+     with CSAR archives, this is read from the metadata file)
+    :type service_template_filename: basestring
+    :return: path to main service template file
+    :rtype: basestring
     """
     if urlparse(source).scheme:
         downloaded_file = utils.download_file(source)
@@ -66,14 +68,15 @@ def get(source, service_template_filename):
 
 
 def _get_service_template_file_from_archive(archive, service_template_filename):
-    """Extract archive to temporary location and get path to service template file.
+    """
+    Extract archive to temporary location and get path to service template file.
 
-    :param archive: Path to archive file
-    :type archive: str
-    :param service_template_filename: Path to service template file relative to archive
-    :type service_template_filename: str
-    :return: Absolute path to service template file
-    :rtype: str
+    :param archive: path to archive file
+    :type archive: basestring
+    :param service_template_filename: path to service template file relative to archive
+    :type service_template_filename: basestring
+    :return: absolute path to service template file
+    :rtype: basestring
 
     """
     if csar.is_csar_archive(archive):
@@ -95,12 +98,13 @@ def _get_service_template_file_from_archive(archive, service_template_filename):
 
 
 def _map_to_github_url(source):
-    """Returns a path to a downloaded github archive.
+    """
+    Returns a path to a downloaded GitHub archive.
 
-    :param source: github repo in the format of `org/repo[:tag/branch]`.
-    :type source: str
-    :return: URL to the archive file for the given repo in github
-    :rtype: str
+    :param source: GitHub repo: ``org/repo[:tag/branch]``
+    :type source: basestring
+    :return: URL to the archive file for the given repo in GitHub
+    :rtype: basestring
 
     """
     source_parts = source.split(':', 1)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/table.py
----------------------------------------------------------------------
diff --git a/aria/cli/table.py b/aria/cli/table.py
index d984c87..74487ae 100644
--- a/aria/cli/table.py
+++ b/aria/cli/table.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Tabular formatting utilities.
+"""
+
 import os
 from datetime import datetime
 
@@ -23,6 +27,23 @@ from .env import logger
 
 def print_data(columns, items, header_text,
                column_formatters=None, col_max_width=None, defaults=None):
+    """
+    Prints data in a tabular form.
+
+    :param columns: columns of the table, e.g. ``['id','name']``
+    :type columns: iterable of basestring
+    :param items: each element must have keys or attributes corresponding to the ``columns`` items,
+     e.g. ``[{'id':'123', 'name':'Pete'}]``
+    :type data: [{:obj:`basestring`: :obj:`basestring`}]
+    :param column_formatters: maps column name to formatter, a function that may manipulate the
+     string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
+    :type column_formatters: {:obj:`basestring`: :obj:`function`}
+    :param col_max_width: maximum width of table
+    :type col_max_width: int
+    :param defaults: default values for keys that don't exist in the data itself, e.g.
+     ``{'serviceId':'123'}``
+    :type defaults: {:obj:`basestring`: :obj:`basestring`}
+    """
     if items is None:
         items = []
     elif not isinstance(items, list):
@@ -43,30 +64,17 @@ def _generate(cols, data, column_formatters=None, defaults=None):
     """
     Return a new PrettyTable instance representing the list.
 
-    Arguments:
-
-        cols - An iterable of strings that specify what
-               are the columns of the table.
-
-               for example: ['id','name']
-
-        data - An iterable of dictionaries or objects, each element must
-               have keys or attributes corresponding to the cols items.
-
-               for example: [{'id':'123', 'name':'Pete'}]
-
-        column_formatters - A dictionary from a column name to a formatter - a function that
-                            may manipulate the string values printed for this column.
-                            (See below for a few built-in formatter examples)
-
-                            for example: {'created_at': timestamp_formatter}
-
-        defaults - A dictionary specifying default values for
-                   key's that don't exist in the data itself.
-
-                   for example: {'serviceId':'123'} will set the
-                   serviceId value for all rows to '123'.
-
+    :param cols: columns of the table, e.g. ``['id','name']``
+    :type cols: iterable of :obj:`basestring`
+    :param data: each element must have keys or attributes corresponding to the ``cols`` items,
+     e.g. ``[{'id':'123', 'name':'Pete'}]``
+    :type data: [{:obj:`basestring`: :obj:`basestring`}]
+    :param column_formatters: maps column name to formatter, a function that may manipulate the
+     string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
+    :type column_formatters: {:obj:`basestring`: :obj:`function`}
+    :param defaults: default values for keys that don't exist in the data itself, e.g.
+     ``{'serviceId':'123'}``
+    :type defaults: {:obj:`basestring`: :obj:`basestring`}
     """
     def get_values_per_column(column, row_data):
         if hasattr(row_data, column) or (isinstance(row_data, dict) and column in row_data):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/cli/utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/utils.py b/aria/cli/utils.py
index 852f24d..697ff37 100644
--- a/aria/cli/utils.py
+++ b/aria/cli/utils.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Miscellaneous CLI utilities.
+"""
+
 import os
 import sys
 from StringIO import StringIO
@@ -44,8 +48,8 @@ def get_parameter_templates_as_string(parameter_templates):
 
 def check_overriding_storage_exceptions(e, model_class, name):
     """
-    This method checks whether the storage exception is a known type where we'd like to override
-     the exception message; If so, it raises a new error. Otherwise it simply returns.
+    Checks whether the storage exception is a known type where we'd like to override the exception
+    message; If so, it raises a new error. Otherwise it simply returns.
     """
     assert isinstance(e, BaseException)
     if 'UNIQUE constraint failed' in e.message:
@@ -68,15 +72,16 @@ def download_file(url):
 
 
 def generate_progress_handler(file_path, action='', max_bar_length=80):
-    """Returns a function that prints a progress bar in the terminal
+    """
+    Returns a function that prints a progress bar in the terminal.
 
-    :param file_path: The name of the file being transferred
-    :param action: Uploading/Downloading
-    :param max_bar_length: Maximum allowed length of the bar. Default: 80
-    :return: The configured print_progress function
+    :param file_path: the name of the file being transferred
+    :param action: uploading/downloading
+    :param max_bar_length: maximum allowed length of the bar
+    :return: configured ``print_progress`` function
     """
-    # We want to limit the maximum line length to 80, but allow for a smaller
-    # terminal size. We also include the action string, and some extra chars
+    # We want to limit the maximum line length to 80, but allow for a smaller terminal size. We also
+    # include the action string, and some extra chars
     terminal_width = get_terminal_size().columns
 
     # This takes care of the case where there is no terminal (e.g. unittest)
@@ -91,24 +96,21 @@ def generate_progress_handler(file_path, action='', max_bar_length=80):
     bar_length -= len(file_name)
 
     def print_progress(read_bytes, total_bytes):
-        """Print upload/download progress on a single line
+        """
+        Print upload/download progress on a single line.
 
-        Call this function in a loop to create a progress bar in the terminal
+        Call this function in a loop to create a progress bar in the terminal.
 
-        :param read_bytes: Number of bytes already processed
-        :param total_bytes: Total number of bytes in the file
+        :param read_bytes: number of bytes already processed
+        :param total_bytes: total number of bytes in the file
         """
 
-        filled_length = min(bar_length, int(round(bar_length * read_bytes /
-                                                  float(total_bytes))))
-        percents = min(100.00, round(
-            100.00 * (read_bytes / float(total_bytes)), 2))
+        filled_length = min(bar_length, int(round(bar_length * read_bytes / float(total_bytes))))
+        percents = min(100.00, round(100.00 * (read_bytes / float(total_bytes)), 2))
         bar = '#' * filled_length + '-' * (bar_length - filled_length)  # pylint: disable=blacklisted-name
 
-        # The \r caret makes sure the cursor moves back to the beginning of
-        # the line
-        sys.stdout.write('\r{0} {1} |{2}| {3}%'.format(
-            action, file_name, bar, percents))
+        # The \r caret makes sure the cursor moves back to the beginning of the line
+        sys.stdout.write('\r{0} {1} |{2}| {3}%'.format(action, file_name, bar, percents))
         if read_bytes >= total_bytes:
             sys.stdout.write(os.linesep)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/core.py
----------------------------------------------------------------------
diff --git a/aria/core.py b/aria/core.py
index f660167..a8d5245 100644
--- a/aria/core.py
+++ b/aria/core.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+ARIA core module.
+"""
+
 from . import exceptions
 from .parser import consumption
 from .parser.loading.location import UriLocation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/exceptions.py b/aria/exceptions.py
index 93987dc..5d3e21d 100644
--- a/aria/exceptions.py
+++ b/aria/exceptions.py
@@ -14,9 +14,7 @@
 # limitations under the License.
 
 """
-ARIA exceptions module
-Every sub-package in ARIA has a module with its exceptions.
-aria.exceptions module conveniently collects all these exceptions for easier imports.
+Base exception classes and other common exceptions used throughout ARIA.
 """
 
 import sys
@@ -48,21 +46,21 @@ class AriaException(Exception):
 
 class DependentServicesError(AriaError):
     """
-    Raised when attempting to delete a service template which has existing services
+    Raised when attempting to delete a service template which has existing services.
     """
     pass
 
 
 class DependentActiveExecutionsError(AriaError):
     """
-    Raised when attempting to delete a service which has active executions
+    Raised when attempting to delete a service which has active executions.
     """
     pass
 
 
 class DependentAvailableNodesError(AriaError):
     """
-    Raised when attempting to delete a service which has available nodes
+    Raised when attempting to delete a service which has available nodes.
     """
     pass
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/extension.py
----------------------------------------------------------------------
diff --git a/aria/extension.py b/aria/extension.py
index 4dba74f..e90750d 100644
--- a/aria/extension.py
+++ b/aria/extension.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Mechanism for registering and loading ARIA extensions.
+"""
+
 # pylint: disable=no-self-use
 
 from .utils import collections
@@ -49,7 +53,9 @@ def _registrar(function):
 
 
 class _ExtensionRegistration(object):
-    """Base class for extension class decorators"""
+    """
+    Base class for extension class decorators.
+    """
 
     def __init__(self):
         self._registrars = {}
@@ -70,7 +76,7 @@ class _ExtensionRegistration(object):
 
     def init(self):
         """
-        Initialize all registrars by calling all registered functions
+        Initialize all registrars by calling all registered functions.
         """
         registered_instances = [cls() for cls in self._registered_classes]
         for name, registrar in self._registrars.items():
@@ -81,13 +87,16 @@ class _ExtensionRegistration(object):
 
 
 class _ParserExtensionRegistration(_ExtensionRegistration):
-    """Parser extensions class decorator"""
+    """
+    Parser extensions class decorator.
+    """
 
     @_registrar
     def presenter_class(self):
         """
         Presentation class registration.
-        Implementing functions can return a single class or a list/tuple of classes
+
+        Implementing functions can return a single class or a list/tuple of classes.
         """
         return []
 
@@ -95,7 +104,8 @@ class _ParserExtensionRegistration(_ExtensionRegistration):
     def specification_package(self):
         """
         Specification package registration.
-        Implementing functions can return a package name or a list/tuple of names
+
+        Implementing functions can return a package name or a list/tuple of names.
         """
         return []
 
@@ -103,7 +113,8 @@ class _ParserExtensionRegistration(_ExtensionRegistration):
     def specification_url(self):
         """
         Specification URL registration.
-        Implementing functions should return a dictionary from names to URLs
+
+        Implementing functions should return a dictionary from names to URLs.
         """
         return {}
 
@@ -111,7 +122,8 @@ class _ParserExtensionRegistration(_ExtensionRegistration):
     def uri_loader_prefix(self):
         """
         URI loader prefix registration.
-        Implementing functions can return a single prefix or a list/tuple of prefixes
+
+        Implementing functions can return a single prefix or a list/tuple of prefixes.
         """
         return collections.StrictList(value_class=basestring)
 
@@ -119,13 +131,15 @@ parser = _ParserExtensionRegistration()
 
 
 class _ProcessExecutorExtensionRegistration(_ExtensionRegistration):
-    """Process executor extension class decorator"""
+    """
+    Process executor extension class decorator.
+    """
 
     @_registrar
     def decorate(self):
         """
         The operation function executed by the process executor will be decorated with the function
-        returned from decorate().
+        returned from ``decorate()``.
         """
         return []
 
@@ -134,7 +148,7 @@ process_executor = _ProcessExecutorExtensionRegistration()
 
 def init():
     """
-    Initialize all registrars by calling all registered functions
+    Initialize all registrars by calling all registered functions.
     """
     parser.init()
     process_executor.init()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index bd7ed4e..f4f6ec9 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 """
-Logging related mixins and functions
+Mix-ins and functions for logging, supporting multiple backends (such as SQL) and consistent
+formatting.
 """
 
 import logging
@@ -38,12 +39,11 @@ _base_logger = logging.getLogger('aria')
 
 class LoggerMixin(object):
     """
-    Mixin Logger Class
-    configuration (class members):
-        logger_name: logger name [default: <class_name>]
-        logger_level: logger level [default: logging.DEBUG]
-        base_logger: This Mixing will create child logger from this base_logger
-                    [default: root logger]
+    Provides logging functionality to a class.
+
+    :ivar logger_name: logger name; default to the class name
+    :ivar logger_level: logger level; defaults to ``logging.DEBUG``
+    :ivar base_logger: child loggers are created from this; defaults to the root logger
     """
     logger_name = None
     logger_level = logging.DEBUG
@@ -66,7 +66,7 @@ class LoggerMixin(object):
             base_logger=logging.getLogger(),
             **kwargs):
         """
-        Set the logger used by the consuming class
+        Set the logger used by the consuming class.
         """
         cls.logger_name = logger_name
         cls.logger_level = logger_level
@@ -86,10 +86,12 @@ class LoggerMixin(object):
 
 def create_logger(logger=_base_logger, handlers=(), **configs):
     """
-
-    :param logging.Logger logger: The logger name [default: aria logger]
-    :param list handlers: The logger handlers
-    :param configs: The logger configurations
+    :param logger: logger name; defaults to ARIA logger
+    :type logger: logging.Logger
+    :param handlers: logger handlers
+    :type handlers: []
+    :param configs: logger configurations
+    :type configs: []
     :return: logger
     """
     logger.handlers = []
@@ -103,10 +105,8 @@ def create_logger(logger=_base_logger, handlers=(), **configs):
 
 def create_console_log_handler(level=logging.DEBUG, formatter=None):
     """
-
     :param level:
     :param formatter:
-    :return:
     """
     console = logging.StreamHandler()
     console.setLevel(level)
@@ -123,10 +123,9 @@ def create_sqla_log_handler(model, log_cls, execution_id, level=logging.DEBUG):
 
 class _DefaultConsoleFormat(logging.Formatter):
     """
-    _DefaultConsoleFormat class
-    Console logger formatter
-     info level logs format: '%(message)s'
-     every other log level are formatted: '%(levelname)s: %(message)s'
+    Info level log format: ``%(message)s``.
+
+    Every other log level is formatted: ``%(levelname)s: %(message)s``.
     """
     def format(self, record):
         try:
@@ -147,7 +146,7 @@ def create_file_log_handler(
         backup_count=10,
         formatter=None):
     """
-    Create a logging.handlers.RotatingFileHandler
+    Create a :class:`logging.handlers.RotatingFileHandler`.
     """
     rotating_file = logging_handlers.RotatingFileHandler(
         filename=file_path,
@@ -161,7 +160,6 @@ def create_file_log_handler(
 
 
 class _SQLAlchemyHandler(logging.Handler):
-
     def __init__(self, model, log_cls, execution_id, **kwargs):
         logging.Handler.__init__(self, **kwargs)
         self._model = model

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/aria/modeling/__init__.py b/aria/modeling/__init__.py
index 4ac79e7..57bc188 100644
--- a/aria/modeling/__init__.py
+++ b/aria/modeling/__init__.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+This package provides an API for modeling ARIA's state and serializing it to storage.
+"""
+
 from collections import namedtuple
 
 from . import (

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/constraints.py
----------------------------------------------------------------------
diff --git a/aria/modeling/constraints.py b/aria/modeling/constraints.py
index 107b010..8ed33d5 100644
--- a/aria/modeling/constraints.py
+++ b/aria/modeling/constraints.py
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Constraints for the requirements-and-capabilities matching mechanism.
+"""
 
 class NodeTemplateConstraint(object):
     """
@@ -23,6 +26,6 @@ class NodeTemplateConstraint(object):
 
     def matches(self, source_node_template, target_node_template):
         """
-        Returns true is the target matches the constraint for the source.
+        Returns ``True`` if the target matches the constraint for the source.
         """
         raise NotImplementedError

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/exceptions.py b/aria/modeling/exceptions.py
index d0e3e22..573efaf 100644
--- a/aria/modeling/exceptions.py
+++ b/aria/modeling/exceptions.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Modeling exceptions.
+"""
+
 from ..exceptions import AriaException
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index 06fd19f..6544adf 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Mechanism for evaluating intrinsic functions.
+"""
+
 from ..parser.consumption import ConsumptionContext
 from ..parser.exceptions import InvalidValueError
 from ..utils.collections import OrderedDict
@@ -34,10 +38,11 @@ class Function(object):
 
     def __evaluate__(self, container_holder):
         """
-        Evaluates the function if possible. If impossible, raises
-        :class:`CannotEvaluateFunctionException` (do not just return None).
+        Evaluates the function if possible.
 
-        :rtype: Evaluation (or any object with ``value`` and ``final`` properties)
+        :rtype: :class:`Evaluation` (or any object with ``value`` and ``final`` properties)
+        :raises CannotEvaluateFunctionException: if cannot be evaluated at this time (do *not* just
+         return ``None``)
         """
 
         raise NotImplementedError
@@ -50,6 +55,10 @@ class Function(object):
 class Evaluation(object):
     """
     An evaluated :class:`Function` return value.
+
+    :ivar value: evaluated value
+    :ivar final: whether the value is final
+    :vartype final: boolean
     """
 
     def __init__(self, value, final=False):
@@ -60,13 +69,13 @@ class Evaluation(object):
 def evaluate(value, container_holder, report_issues=False): # pylint: disable=too-many-branches
     """
     Recursively attempts to call ``__evaluate__``. If an evaluation occurred will return an
-    :class:`Evaluation`, otherwise it will be None. If any evaluation is non-final, then the entire
-    evaluation will also be non-final.
+    :class:`Evaluation`, otherwise it will be ``None``. If any evaluation is non-final, then the
+    entire evaluation will also be non-final.
 
     The ``container_holder`` argument should have three properties: ``container`` should return
     the model that contains the value, ``service`` should return the containing
-    :class:`aria.modeling.models.Service` model or None, and ``service_template`` should return the
-    containing :class:`aria.modeling.models.ServiceTemplate` model or None.
+    :class:`~aria.modeling.models.Service` model or None, and ``service_template`` should return the
+    containing :class:`~aria.modeling.models.ServiceTemplate` model or ``None``.
     """
 
     evaluated = False


[05/15] incubator-ariatosca git commit: ARIA-285 Cancel execution may leave running processes

Posted by em...@apache.org.
ARIA-285 Cancel execution may leave running processes


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/7bba3ab1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/7bba3ab1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/7bba3ab1

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 7bba3ab13e344425e86b14ff708030f76061d3f7
Parents: 807db30
Author: max-orlov <ma...@gigaspaces.com>
Authored: Sun Jun 25 12:19:02 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Tue Jun 27 17:18:48 2017 +0300

----------------------------------------------------------------------
 aria/orchestrator/workflows/core/engine.py      | 10 ++++
 aria/orchestrator/workflows/executor/base.py    |  9 +++-
 aria/orchestrator/workflows/executor/celery.py  | 16 +++---
 aria/orchestrator/workflows/executor/process.py | 51 +++++++++++++++----
 requirements.in                                 |  1 +
 requirements.txt                                |  1 +
 .../orchestrator/workflows/executor/__init__.py |  7 +++
 .../workflows/executor/test_process_executor.py | 52 +++++++++++++++++++-
 tests/requirements.txt                          |  1 +
 9 files changed, 129 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/aria/orchestrator/workflows/core/engine.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/engine.py b/aria/orchestrator/workflows/core/engine.py
index d52ae85..5a94df8 100644
--- a/aria/orchestrator/workflows/core/engine.py
+++ b/aria/orchestrator/workflows/core/engine.py
@@ -66,13 +66,23 @@ class Engine(logger.LoggerMixin):
                 else:
                     time.sleep(0.1)
             if cancel:
+                self._terminate_tasks(tasks_tracker.executing_tasks)
                 events.on_cancelled_workflow_signal.send(ctx)
             else:
                 events.on_success_workflow_signal.send(ctx)
         except BaseException as e:
+            # Cleanup any remaining tasks
+            self._terminate_tasks(tasks_tracker.executing_tasks)
             events.on_failure_workflow_signal.send(ctx, exception=e)
             raise
 
+    def _terminate_tasks(self, tasks):
+        for task in tasks:
+            try:
+                self._executors[task._executor].terminate(task.id)
+            except BaseException:
+                pass
+
     @staticmethod
     def cancel_execution(ctx):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/aria/orchestrator/workflows/executor/base.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/base.py b/aria/orchestrator/workflows/executor/base.py
index 6a3c9d2..4cc4503 100644
--- a/aria/orchestrator/workflows/executor/base.py
+++ b/aria/orchestrator/workflows/executor/base.py
@@ -25,7 +25,7 @@ class BaseExecutor(logger.LoggerMixin):
     """
     Base class for executors for running tasks
     """
-    def _execute(self, task):
+    def _execute(self, ctx):
         raise NotImplementedError
 
     def execute(self, ctx):
@@ -48,6 +48,13 @@ class BaseExecutor(logger.LoggerMixin):
         """
         pass
 
+    def terminate(self, ctx):
+        """
+        Terminate the executing task
+        :return:
+        """
+        pass
+
     @staticmethod
     def _task_started(ctx):
         events.start_task_signal.send(ctx)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/aria/orchestrator/workflows/executor/celery.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/celery.py b/aria/orchestrator/workflows/executor/celery.py
index 9d66d26..46b15fd 100644
--- a/aria/orchestrator/workflows/executor/celery.py
+++ b/aria/orchestrator/workflows/executor/celery.py
@@ -42,15 +42,15 @@ class CeleryExecutor(BaseExecutor):
         self._receiver_thread.start()
         self._started_queue.get(timeout=30)
 
-    def _execute(self, task):
-        self._tasks[task.id] = task
-        arguments = dict(arg.unwrapped for arg in task.arguments.values())
-        arguments['ctx'] = task.context
-        self._results[task.id] = self._app.send_task(
-            task.operation_mapping,
+    def _execute(self, ctx):
+        self._tasks[ctx.id] = ctx
+        arguments = dict(arg.unwrapped for arg in ctx.arguments.values())
+        arguments['ctx'] = ctx.context
+        self._results[ctx.id] = self._app.send_task(
+            ctx.operation_mapping,
             kwargs=arguments,
-            task_id=task.id,
-            queue=self._get_queue(task))
+            task_id=ctx.id,
+            queue=self._get_queue(ctx))
 
     def close(self):
         self._stopped = True

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/aria/orchestrator/workflows/executor/process.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/process.py b/aria/orchestrator/workflows/executor/process.py
index 8518b33..11e3cfd 100644
--- a/aria/orchestrator/workflows/executor/process.py
+++ b/aria/orchestrator/workflows/executor/process.py
@@ -25,6 +25,10 @@ import sys
 # As part of the process executor implementation, subprocess are started with this module as their
 # entry point. We thus remove this module's directory from the python path if it happens to be
 # there
+
+import signal
+from collections import namedtuple
+
 script_dir = os.path.dirname(__file__)
 if script_dir in sys.path:
     sys.path.remove(script_dir)
@@ -39,6 +43,7 @@ import tempfile
 import Queue
 import pickle
 
+import psutil
 import jsonpickle
 
 import aria
@@ -57,6 +62,9 @@ UPDATE_TRACKED_CHANGES_FAILED_STR = \
     'Some changes failed writing to storage. For more info refer to the log.'
 
 
+_Task = namedtuple('_Task', 'proc, ctx')
+
+
 class ProcessExecutor(base.BaseExecutor):
     """
     Executor which runs tasks in a subprocess environment
@@ -113,9 +121,26 @@ class ProcessExecutor(base.BaseExecutor):
         self._server_socket.close()
         self._listener_thread.join(timeout=60)
 
+        for task_id in self._tasks:
+            self.terminate(task_id)
+
+    def terminate(self, task_id):
+        task = self._remove_task(task_id)
+        # The process might have managed to finish, thus it would not be in the tasks list
+        if task:
+            try:
+                parent_process = psutil.Process(task.proc.pid)
+                for child_process in reversed(parent_process.children(recursive=True)):
+                    try:
+                        child_process.send_signal(signal.SIGKILL)
+                    except BaseException:
+                        pass
+                parent_process.send_signal(signal.SIGKILL)
+            except BaseException:
+                pass
+
     def _execute(self, ctx):
         self._check_closed()
-        self._tasks[ctx.task.id] = ctx
 
         # Temporary file used to pass arguments to the started subprocess
         file_descriptor, arguments_json_path = tempfile.mkstemp(prefix='executor-', suffix='.json')
@@ -125,13 +150,18 @@ class ProcessExecutor(base.BaseExecutor):
 
         env = self._construct_subprocess_env(task=ctx.task)
         # Asynchronously start the operation in a subprocess
-        subprocess.Popen(
-            '{0} {1} {2}'.format(sys.executable, __file__, arguments_json_path),
-            env=env,
-            shell=True)
+        proc = subprocess.Popen(
+            [
+                sys.executable,
+                os.path.expanduser(os.path.expandvars(__file__)),
+                os.path.expanduser(os.path.expandvars(arguments_json_path))
+            ],
+            env=env)
+
+        self._tasks[ctx.task.id] = _Task(ctx=ctx, proc=proc)
 
     def _remove_task(self, task_id):
-        return self._tasks.pop(task_id)
+        return self._tasks.pop(task_id, None)
 
     def _check_closed(self):
         if self._stopped:
@@ -191,15 +221,18 @@ class ProcessExecutor(base.BaseExecutor):
                 _send_message(connection, response)
 
     def _handle_task_started_request(self, task_id, **kwargs):
-        self._task_started(self._tasks[task_id])
+        self._task_started(self._tasks[task_id].ctx)
 
     def _handle_task_succeeded_request(self, task_id, **kwargs):
         task = self._remove_task(task_id)
-        self._task_succeeded(task)
+        if task:
+            self._task_succeeded(task.ctx)
 
     def _handle_task_failed_request(self, task_id, request, **kwargs):
         task = self._remove_task(task_id)
-        self._task_failed(task, exception=request['exception'], traceback=request['traceback'])
+        if task:
+            self._task_failed(
+                task.ctx, exception=request['exception'], traceback=request['traceback'])
 
 
 def _send_message(connection, message):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/requirements.in
----------------------------------------------------------------------
diff --git a/requirements.in b/requirements.in
index cecc9fd..723ed51 100644
--- a/requirements.in
+++ b/requirements.in
@@ -33,6 +33,7 @@ PrettyTable>=0.7,<0.8
 click_didyoumean==0.0.3
 backports.shutil_get_terminal_size==1.0.0
 logutils==0.3.4.1
+psutil>=5.2.2, < 6.0.0
 importlib ; python_version < '2.7'
 ordereddict ; python_version < '2.7'
 total-ordering ; python_version < '2.7'  # only one version on pypi

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index 9f929a9..7ee1008 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,6 +26,7 @@ networkx==1.9.1
 ordereddict==1.1 ; python_version < "2.7"
 packaging==16.8           # via setuptools
 prettytable==0.7.2
+psutil==5.2.2
 pyparsing==2.2.0          # via packaging
 requests==2.13.0
 retrying==1.3.3

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/tests/orchestrator/workflows/executor/__init__.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/__init__.py b/tests/orchestrator/workflows/executor/__init__.py
index 83584a6..99d0b39 100644
--- a/tests/orchestrator/workflows/executor/__init__.py
+++ b/tests/orchestrator/workflows/executor/__init__.py
@@ -18,10 +18,13 @@ from contextlib import contextmanager
 
 import aria
 from aria.modeling import models
+from aria.orchestrator.context.common import BaseContext
 
 
 class MockContext(object):
 
+    INSTRUMENTATION_FIELDS = BaseContext.INSTRUMENTATION_FIELDS
+
     def __init__(self, storage, task_kwargs=None):
         self.logger = logging.getLogger('mock_logger')
         self._task_kwargs = task_kwargs or {}
@@ -46,6 +49,10 @@ class MockContext(object):
     def close(self):
         pass
 
+    @property
+    def model(self):
+        return self._storage
+
     @classmethod
     def instantiate_from_dict(cls, storage_kwargs=None, task_kwargs=None):
         return cls(storage=aria.application_model_storage(**(storage_kwargs or {})),

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/tests/orchestrator/workflows/executor/test_process_executor.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor.py b/tests/orchestrator/workflows/executor/test_process_executor.py
index 755b9be..6f5c827 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor.py
@@ -14,17 +14,24 @@
 # limitations under the License.
 
 import os
+import time
 import Queue
+import subprocess
 
 import pytest
+import psutil
+import retrying
 
 import aria
+from aria import operation
+from aria.modeling import models
 from aria.orchestrator import events
 from aria.utils.plugin import create as create_plugin
 from aria.orchestrator.workflows.executor import process
 
 import tests.storage
 import tests.resources
+from tests.helpers import FilesystemDataHolder
 from tests.fixtures import (  # pylint: disable=unused-import
     plugins_dir,
     plugin_manager,
@@ -71,10 +78,45 @@ class TestProcessExecutor(object):
             executor.execute(MockContext(model, task_kwargs=dict(function='some.function')))
         assert 'closed' in exc_info.value.message
 
+    def test_process_termination(self, executor, model, fs_test_holder):
+        argument = models.Argument.wrap('holder_path', fs_test_holder._path)
+        model.argument.put(argument)
+        ctx = MockContext(
+            model,
+            task_kwargs=dict(
+                function='{0}.{1}'.format(__name__, freezing_task.__name__),
+                arguments=dict(holder_path=argument)),
+        )
+
+        executor.execute(ctx)
+
+        @retrying.retry(retry_on_result=lambda r: r is False, stop_max_delay=60000, wait_fixed=500)
+        def wait_for_extra_process_id():
+            return fs_test_holder.get('subproc', False)
+
+        pids = [executor._tasks[ctx.task.id].proc.pid, wait_for_extra_process_id()]
+        assert any(p.pid == pid for p in psutil.process_iter() for pid in pids)
+        executor.terminate(ctx.task.id)
+
+        # Give a chance to the processes to terminate
+        time.sleep(2)
+        assert not any(p.pid == pid and p.status() != psutil.STATUS_ZOMBIE
+                       for p in psutil.process_iter()
+                       for pid in pids)
+
+
+@pytest.fixture
+def fs_test_holder(tmpdir):
+    dataholder_path = str(tmpdir.join('dataholder'))
+    holder = FilesystemDataHolder(dataholder_path)
+    return holder
+
 
 @pytest.fixture
 def executor(plugin_manager):
-    result = process.ProcessExecutor(plugin_manager=plugin_manager)
+    result = process.ProcessExecutor(
+        plugin_manager=plugin_manager,
+        python_path=[tests.ROOT_DIR])
     yield result
     result.close()
 
@@ -92,3 +134,11 @@ def model(tmpdir):
                                               initiator_kwargs=dict(base_dir=str(tmpdir)))
     yield _storage
     tests.storage.release_sqlite_storage(_storage)
+
+
+@operation
+def freezing_task(holder_path, **_):
+    holder = FilesystemDataHolder(holder_path)
+    holder['subproc'] = subprocess.Popen('while true; do sleep 5; done', shell=True).pid
+    while True:
+        time.sleep(5)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/7bba3ab1/tests/requirements.txt
----------------------------------------------------------------------
diff --git a/tests/requirements.txt b/tests/requirements.txt
index 71a227a..cf57821 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -13,6 +13,7 @@
 testtools
 fasteners==0.13.0
 sh==1.12.13
+psutil==5.2.2
 mock==1.0.1
 pylint==1.6.4
 pytest==3.0.2


[09/15] incubator-ariatosca git commit: ARIA-286 Sphinx documentation for code and CLI

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/type.py
----------------------------------------------------------------------
diff --git a/aria/utils/type.py b/aria/utils/type.py
index f08159a..fe88a62 100644
--- a/aria/utils/type.py
+++ b/aria/utils/type.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Type utilities.
+"""
+
 import datetime
 
 from .specification import implements_specification
@@ -79,7 +83,7 @@ def full_type_name(value):
 @implements_specification('3.2.1-1', 'tosca-simple-1.0')
 def canonical_type_name(value):
     """
-    Returns the canonical TOSCA type name of a primitive value, or None if unknown.
+    Returns the canonical TOSCA type name of a primitive value, or ``None`` if unknown.
 
     For a list of TOSCA type names, see the `TOSCA Simple Profile v1.0
     cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
@@ -95,7 +99,7 @@ def canonical_type_name(value):
 @implements_specification('3.2.1-2', 'tosca-simple-1.0')
 def canonical_type(type_name):
     """
-    Return the canonical type for any Python, YAML, or TOSCA type name or alias, or None if
+    Return the canonical type for any Python, YAML, or TOSCA type name or alias, or ``None`` if
     unsupported.
 
     :param type_name: Type name (case insensitive)
@@ -109,9 +113,8 @@ def validate_value_type(value, type_name):
     Validate that a value is of a specific type. Supports Python, YAML, and TOSCA type names and
     aliases.
 
-    A ValueError will be raised on type mismatch.
-
-    :param type_name: Type name (case insensitive)
+    :param type_name: type name (case insensitive)
+    :raises ~exceptions.ValueError: on type mismatch
     """
 
     the_type = canonical_type(type_name)
@@ -132,9 +135,8 @@ def convert_value_to_type(str_value, python_type_name):
     """
     Converts a value to a specific Python primitive type.
 
-    A ValueError will be raised for unsupported types or conversion failure.
-
     :param python_type_name: Python primitive type name (case insensitive)
+    :raises ~exceptions.ValueError: for unsupported types or conversion failure
     """
 
     python_type_name = python_type_name.lower()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/uris.py
----------------------------------------------------------------------
diff --git a/aria/utils/uris.py b/aria/utils/uris.py
index 5f7bcf5..49881f2 100644
--- a/aria/utils/uris.py
+++ b/aria/utils/uris.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+URI utilities.
+"""
+
 import os
 import urlparse
 
@@ -22,8 +26,8 @@ _IS_WINDOWS = (os.name == 'nt')
 
 def as_file(uri):
     """
-    If the URI is a file (either the :code:`file` scheme or no scheme), then returns the normalized
-    path. Otherwise, returns None.
+    If the URI is a file (either the ``file`` scheme or no scheme), then returns the normalized
+    path. Otherwise, returns ``None``.
     """
 
     if _IS_WINDOWS:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/uuid.py
----------------------------------------------------------------------
diff --git a/aria/utils/uuid.py b/aria/utils/uuid.py
index 1f340c6..d6c9ced 100644
--- a/aria/utils/uuid.py
+++ b/aria/utils/uuid.py
@@ -13,6 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+UUID generation utilities.
+"""
+
 from __future__ import absolute_import  # so we can import standard 'uuid'
 
 from random import randrange
@@ -32,14 +36,14 @@ def generate_uuid(length=None, variant='base57'):
     """
     A random string with varying degrees of guarantee of universal uniqueness.
 
-    :param variant: options are:
-                    * 'base57' (the default) uses a mix of upper and lowercase alphanumerics
-                      ensuring no visually ambiguous characters; default length 22
-                    * 'alphanumeric' uses lowercase alphanumeric; default length 25
-                    * 'uuid' user lowercase hexadecimal in the classic UUID format, including
-                      dashes; length is always 36
-                    * 'hex' uses lowercase hexadecimal characters but has no guarantee of
-                      uniqueness; default length of 5
+    :param variant:
+     * ``base57`` (the default) uses a mix of upper and lowercase alphanumerics ensuring no visually
+       ambiguous characters; default length 22
+     * ``alphanumeric`` uses lowercase alphanumeric; default length 25
+     * ``uuid`` uses lowercase hexadecimal in the classic UUID format, including dashes; length is
+       always 36
+     * ``hex`` uses lowercase hexadecimal characters but has no guarantee of uniqueness; default
+       length of 5
     """
 
     if variant == 'base57':

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/validation.py
----------------------------------------------------------------------
diff --git a/aria/utils/validation.py b/aria/utils/validation.py
index 193cb33..3452dcc 100644
--- a/aria/utils/validation.py
+++ b/aria/utils/validation.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-Contains validation related utilities
+Validation utilities.
 """
 
 from .formatting import string_list_as_string
@@ -22,7 +22,7 @@ from .formatting import string_list_as_string
 
 class ValidatorMixin(object):
     """
-    A mixin that should be added to classes that require validating user input
+    A mix0in that should be added to classes that require validating user input.
     """
 
     _ARGUMENT_TYPE_MESSAGE = '{name} argument must be {type} based, got {arg!r}'
@@ -68,7 +68,7 @@ class ValidatorMixin(object):
 def validate_function_arguments(func, func_kwargs):
     """
     Validates all required arguments are supplied to ``func`` and that no additional arguments are
-    supplied
+    supplied.
     """
 
     _kwargs_flags = 8

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/aria/utils/versions.py
----------------------------------------------------------------------
diff --git a/aria/utils/versions.py b/aria/utils/versions.py
index 925f59e..521004c 100644
--- a/aria/utils/versions.py
+++ b/aria/utils/versions.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 """
-General-purpose version string handling
+Verion string utilities.
 """
 
 import re
@@ -55,8 +55,9 @@ class VersionString(unicode):
     Any value that does not conform to this format will be treated as a zero version, which would
     be lesser than any non-zero version.
 
-    For efficient list sorts use the ``key`` property, e.g.:
-    ``sorted(versions, key=lambda x: x.key)``
+    For efficient list sorts use the ``key`` property, e.g.::
+
+        sorted(versions, key=lambda x: x.key)
     """
 
     NULL = None # initialized below
@@ -84,9 +85,9 @@ def parse_version_string(version): # pylint: disable=too-many-branches
     """
     Parses a version string.
 
-    :param version: The version string
-    :returns: The primary tuple and qualifier float
-    :rtype: ((int), float)
+    :param version: version string
+    :returns: primary tuple and qualifier float
+    :rtype: ((:obj:`int`), :obj:`float`)
     """
 
     if version is None:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.cli.rst
----------------------------------------------------------------------
diff --git a/docs/aria.cli.rst b/docs/aria.cli.rst
new file mode 100644
index 0000000..c325cf0
--- /dev/null
+++ b/docs/aria.cli.rst
@@ -0,0 +1,100 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria.cli`
+===============
+
+.. automodule:: aria.cli
+
+:mod:`aria.cli.color`
+---------------------
+
+.. automodule:: aria.cli.color
+
+:mod:`aria.cli.csar`
+--------------------
+
+.. automodule:: aria.cli.csar
+
+:mod:`aria.cli.defaults`
+------------------------
+
+.. automodule:: aria.cli.defaults
+
+:mod:`aria.cli.exceptions`
+--------------------------
+
+.. automodule:: aria.cli.exceptions
+
+:mod:`aria.cli.execution_logging`
+---------------------------------
+
+.. automodule:: aria.cli.execution_logging
+
+:mod:`aria.cli.helptexts`
+-------------------------
+
+.. automodule:: aria.cli.helptexts
+
+:mod:`aria.cli.inputs`
+----------------------
+
+.. automodule:: aria.cli.inputs
+
+:mod:`aria.cli.logger`
+----------------------
+
+.. automodule:: aria.cli.logger
+
+:mod:`aria.cli.main`
+--------------------
+
+.. automodule:: aria.cli.main
+
+:mod:`aria.cli.service_template_utils`
+--------------------------------------
+
+.. automodule:: aria.cli.service_template_utils
+
+:mod:`aria.cli.table`
+---------------------
+
+.. automodule:: aria.cli.table
+
+:mod:`aria.cli.utils`
+---------------------
+
+.. automodule:: aria.cli.utils
+
+:mod:`aria.cli.config`
+----------------------
+
+.. automodule:: aria.cli.config
+
+:mod:`aria.cli.config.config`
+-----------------------------
+
+.. automodule:: aria.cli.config.config
+
+:mod:`aria.cli.core`
+--------------------
+
+.. automodule:: aria.cli.core
+
+:mod:`aria.cli.core.aria`
+-------------------------
+
+.. automodule:: aria.cli.core.aria

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.modeling.models.rst
----------------------------------------------------------------------
diff --git a/docs/aria.modeling.models.rst b/docs/aria.modeling.models.rst
new file mode 100644
index 0000000..6431780
--- /dev/null
+++ b/docs/aria.modeling.models.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria.modeling.models`
+===========================
+
+.. automodule:: aria.modeling.models
+   :no-show-inheritance:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.modeling.rst
----------------------------------------------------------------------
diff --git a/docs/aria.modeling.rst b/docs/aria.modeling.rst
new file mode 100644
index 0000000..b85e22c
--- /dev/null
+++ b/docs/aria.modeling.rst
@@ -0,0 +1,56 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.modeling`
+====================
+
+.. automodule:: aria.modeling
+
+:mod:`aria.modeling.constraints`
+--------------------------------
+
+.. automodule:: aria.modeling.constraints
+
+:mod:`aria.modeling.exceptions`
+-------------------------------
+
+.. automodule:: aria.modeling.exceptions
+
+:mod:`aria.modeling.functions`
+------------------------------
+
+.. automodule:: aria.modeling.functions
+
+:mod:`aria.modeling.mixins`
+---------------------------
+
+.. automodule:: aria.modeling.mixins
+
+:mod:`aria.modeling.relationship`
+---------------------------------
+
+.. automodule:: aria.modeling.relationship
+
+:mod:`aria.modeling.types`
+--------------------------
+
+.. automodule:: aria.modeling.types
+
+:mod:`aria.modeling.utils`
+--------------------------
+
+.. automodule:: aria.modeling.utils

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.context.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.context.rst b/docs/aria.orchestrator.context.rst
new file mode 100644
index 0000000..395befc
--- /dev/null
+++ b/docs/aria.orchestrator.context.rst
@@ -0,0 +1,46 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.context`
+================================
+
+.. automodule:: aria.orchestrator.context
+
+:mod:`aria.orchestrator.context.common`
+---------------------------------------
+
+.. automodule:: aria.orchestrator.context.common
+
+:mod:`aria.orchestrator.context.exceptions`
+-------------------------------------------
+
+.. automodule:: aria.orchestrator.context.exceptions
+
+:mod:`aria.orchestrator.context.operation`
+------------------------------------------
+
+.. automodule:: aria.orchestrator.context.operation
+
+:mod:`aria.orchestrator.context.toolbelt`
+-----------------------------------------
+
+.. automodule:: aria.orchestrator.context.toolbelt
+
+:mod:`aria.orchestrator.context.workflow`
+-----------------------------------------
+
+.. automodule:: aria.orchestrator.context.workflow

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.execution_plugin.ctx_proxy.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.execution_plugin.ctx_proxy.rst b/docs/aria.orchestrator.execution_plugin.ctx_proxy.rst
new file mode 100644
index 0000000..47ed598
--- /dev/null
+++ b/docs/aria.orchestrator.execution_plugin.ctx_proxy.rst
@@ -0,0 +1,31 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.execution_plugin.ctx_proxy`
+===================================================
+
+.. automodule:: aria.orchestrator.execution_plugin.ctx_proxy
+
+:mod:`aria.orchestrator.execution_plugin.ctx_proxy.client`
+----------------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.ctx_proxy.client
+
+:mod:`aria.orchestrator.execution_plugin.ctx_proxy.server`
+----------------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.ctx_proxy.server

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.execution_plugin.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.execution_plugin.rst b/docs/aria.orchestrator.execution_plugin.rst
new file mode 100644
index 0000000..177a316
--- /dev/null
+++ b/docs/aria.orchestrator.execution_plugin.rst
@@ -0,0 +1,56 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.execution_plugin`
+=========================================
+
+.. automodule:: aria.orchestrator.execution_plugin
+
+:mod:`aria.orchestrator.execution_plugin.common`
+------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.common
+
+:mod:`aria.orchestrator.execution_plugin.constants`
+---------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.constants
+
+:mod:`aria.orchestrator.execution_plugin.environment_globals`
+-------------------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.environment_globals
+
+:mod:`aria.orchestrator.execution_plugin.exceptions`
+----------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.exceptions
+
+:mod:`aria.orchestrator.execution_plugin.instantiation`
+-------------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.instantiation
+
+:mod:`aria.orchestrator.execution_plugin.local`
+-----------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.local
+
+:mod:`aria.orchestrator.execution_plugin.operations`
+----------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.operations

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.execution_plugin.ssh.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.execution_plugin.ssh.rst b/docs/aria.orchestrator.execution_plugin.ssh.rst
new file mode 100644
index 0000000..8bbaa57
--- /dev/null
+++ b/docs/aria.orchestrator.execution_plugin.ssh.rst
@@ -0,0 +1,31 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.execution_plugin.ssh`
+=============================================
+
+.. automodule:: aria.orchestrator.execution_plugin.ssh
+
+:mod:`aria.orchestrator.execution_plugin.ssh.operations`
+--------------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.ssh.operations
+
+:mod:`aria.orchestrator.execution_plugin.ssh.tunnel`
+----------------------------------------------------
+
+.. automodule:: aria.orchestrator.execution_plugin.ssh.tunnel

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.rst b/docs/aria.orchestrator.rst
new file mode 100644
index 0000000..33454e6
--- /dev/null
+++ b/docs/aria.orchestrator.rst
@@ -0,0 +1,46 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator`
+========================
+
+.. automodule:: aria.orchestrator
+
+:mod:`aria.orchestrator.decorators`
+-----------------------------------
+
+.. automodule:: aria.orchestrator.decorators
+
+:mod:`aria.orchestrator.events`
+-------------------------------
+
+.. automodule:: aria.orchestrator.events
+
+:mod:`aria.orchestrator.exceptions`
+-----------------------------------
+
+.. automodule:: aria.orchestrator.exceptions
+
+:mod:`aria.orchestrator.plugin`
+-------------------------------
+
+.. automodule:: aria.orchestrator.plugin
+
+:mod:`aria.orchestrator.workflow_runner`
+----------------------------------------
+
+.. automodule:: aria.orchestrator.workflow_runner

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.workflows.api.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.workflows.api.rst b/docs/aria.orchestrator.workflows.api.rst
new file mode 100644
index 0000000..7ecac75
--- /dev/null
+++ b/docs/aria.orchestrator.workflows.api.rst
@@ -0,0 +1,31 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.workflows.api`
+======================================
+
+.. automodule:: aria.orchestrator.workflows.api
+
+:mod:`aria.orchestrator.workflows.api.task_graph`
+-------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.api.task_graph
+
+:mod:`aria.orchestrator.workflows.api.task`
+-------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.api.task

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.workflows.builtin.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.workflows.builtin.rst b/docs/aria.orchestrator.workflows.builtin.rst
new file mode 100644
index 0000000..de1a8f9
--- /dev/null
+++ b/docs/aria.orchestrator.workflows.builtin.rst
@@ -0,0 +1,57 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+
+:mod:`aria.orchestrator.workflows.builtin`
+==========================================
+
+.. automodule:: aria.orchestrator.workflows.builtin
+
+:mod:`aria.orchestrator.workflows.builtin.execute_operation`
+------------------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.execute_operation
+
+:mod:`aria.orchestrator.workflows.builtin.heal`
+-----------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.heal
+
+:mod:`aria.orchestrator.workflows.builtin.install`
+--------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.install
+
+:mod:`aria.orchestrator.workflows.builtin.start`
+------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.start
+
+:mod:`aria.orchestrator.workflows.builtin.stop`
+-----------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.stop
+
+:mod:`aria.orchestrator.workflows.builtin.uninstall`
+----------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.uninstall
+
+:mod:`aria.orchestrator.workflows.builtin.workflows`
+----------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.builtin.workflows

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.workflows.executor.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.workflows.executor.rst b/docs/aria.orchestrator.workflows.executor.rst
new file mode 100644
index 0000000..cde0a77
--- /dev/null
+++ b/docs/aria.orchestrator.workflows.executor.rst
@@ -0,0 +1,46 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.workflows.executor`
+===========================================
+
+.. automodule:: aria.orchestrator.workflows.executor
+
+:mod:`aria.orchestrator.workflows.executor.base`
+------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.executor.base
+
+:mod:`aria.orchestrator.workflows.executor.celery`
+--------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.executor.celery
+
+:mod:`aria.orchestrator.workflows.executor.dry`
+-----------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.executor.dry
+
+:mod:`aria.orchestrator.workflows.executor.process`
+---------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.executor.process
+
+:mod:`aria.orchestrator.workflows.executor.thread`
+--------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.executor.thread

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.orchestrator.workflows.rst
----------------------------------------------------------------------
diff --git a/docs/aria.orchestrator.workflows.rst b/docs/aria.orchestrator.workflows.rst
new file mode 100644
index 0000000..12f8d9d
--- /dev/null
+++ b/docs/aria.orchestrator.workflows.rst
@@ -0,0 +1,51 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.orchestrator.workflows`
+==================================
+
+.. automodule:: aria.orchestrator.workflows
+
+:mod:`aria.orchestrator.workflows.events_logging`
+-------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.events_logging
+
+:mod:`aria.orchestrator.workflows.exceptions`
+---------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.exceptions
+
+:mod:`aria.orchestrator.workflows.core`
+---------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.core
+
+:mod:`aria.orchestrator.workflows.core.compile`
+-----------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.core.compile
+
+:mod:`aria.orchestrator.workflows.core.engine`
+----------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.core.engine
+
+:mod:`aria.orchestrator.workflows.core.events_handler`
+------------------------------------------------------
+
+.. automodule:: aria.orchestrator.workflows.core.events_handler

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.consumption.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.consumption.rst b/docs/aria.parser.consumption.rst
new file mode 100644
index 0000000..3d9fc6e
--- /dev/null
+++ b/docs/aria.parser.consumption.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.consumption`
+==============================
+
+.. automodule:: aria.parser.consumption

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.loading.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.loading.rst b/docs/aria.parser.loading.rst
new file mode 100644
index 0000000..0ae7565
--- /dev/null
+++ b/docs/aria.parser.loading.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.loading`
+==========================
+
+.. automodule:: aria.parser.loading

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.modeling.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.modeling.rst b/docs/aria.parser.modeling.rst
new file mode 100644
index 0000000..16c359c
--- /dev/null
+++ b/docs/aria.parser.modeling.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.modeling`
+===========================
+
+.. automodule:: aria.parser.modeling

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.presentation.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.presentation.rst b/docs/aria.parser.presentation.rst
new file mode 100644
index 0000000..6c63b2e
--- /dev/null
+++ b/docs/aria.parser.presentation.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.presentation`
+===============================
+
+.. automodule:: aria.parser.presentation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.reading.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.reading.rst b/docs/aria.parser.reading.rst
new file mode 100644
index 0000000..b1d4f6c
--- /dev/null
+++ b/docs/aria.parser.reading.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.reading`
+==========================
+
+.. automodule:: aria.parser.reading

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.rst b/docs/aria.parser.rst
new file mode 100644
index 0000000..700f03d
--- /dev/null
+++ b/docs/aria.parser.rst
@@ -0,0 +1,31 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser`
+==================
+
+.. automodule:: aria.parser
+
+:mod:`aria.parser.exceptions`
+-----------------------------
+
+.. automodule:: aria.parser.exceptions
+
+:mod:`aria.parser.specification`
+--------------------------------
+
+.. automodule:: aria.parser.specification

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.parser.validation.rst
----------------------------------------------------------------------
diff --git a/docs/aria.parser.validation.rst b/docs/aria.parser.validation.rst
new file mode 100644
index 0000000..621898b
--- /dev/null
+++ b/docs/aria.parser.validation.rst
@@ -0,0 +1,21 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.parser.validation`
+=============================
+
+.. automodule:: aria.parser.validation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.rst
----------------------------------------------------------------------
diff --git a/docs/aria.rst b/docs/aria.rst
new file mode 100644
index 0000000..1a0dae5
--- /dev/null
+++ b/docs/aria.rst
@@ -0,0 +1,40 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria`
+===========
+
+.. automodule:: aria
+
+:mod:`aria.core`
+----------------
+
+.. automodule:: aria.core
+
+:mod:`aria.exceptions`
+----------------------
+
+.. automodule:: aria.exceptions
+
+:mod:`aria.extension`
+---------------------
+
+.. automodule:: aria.extension
+
+:mod:`aria.logger`
+------------------
+
+.. automodule:: aria.logger

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.storage.rst
----------------------------------------------------------------------
diff --git a/docs/aria.storage.rst b/docs/aria.storage.rst
new file mode 100644
index 0000000..7c51c2f
--- /dev/null
+++ b/docs/aria.storage.rst
@@ -0,0 +1,51 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.storage`
+===================
+
+.. automodule:: aria.storage
+
+:mod:`aria.storage.api`
+-----------------------
+
+.. automodule:: aria.storage.api
+
+:mod:`aria.storage.collection_instrumentation`
+----------------------------------------------
+
+.. automodule:: aria.storage.collection_instrumentation
+
+:mod:`aria.storage.core`
+------------------------
+
+.. automodule:: aria.storage.core
+
+:mod:`aria.storage.exceptions`
+------------------------------
+
+.. automodule:: aria.storage.exceptions
+
+:mod:`aria.storage.filesystem_rapi`
+-----------------------------------
+
+.. automodule:: aria.storage.filesystem_rapi
+
+:mod:`aria.storage.sql_mapi`
+----------------------------
+
+.. automodule:: aria.storage.sql_mapi

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria.utils.rst
----------------------------------------------------------------------
diff --git a/docs/aria.utils.rst b/docs/aria.utils.rst
new file mode 100644
index 0000000..220c0cd
--- /dev/null
+++ b/docs/aria.utils.rst
@@ -0,0 +1,121 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+:mod:`aria.utils`
+=================
+
+.. automodule:: aria.utils
+
+:mod:`aria.utils.archive`
+-------------------------
+
+.. automodule:: aria.utils.archive
+
+:mod:`aria.utils.argparse`
+--------------------------
+
+.. automodule:: aria.utils.argparse
+
+:mod:`aria.utils.caching`
+-------------------------
+
+.. automodule:: aria.utils.caching
+
+:mod:`aria.utils.collections`
+-----------------------------
+
+.. automodule:: aria.utils.collections
+
+:mod:`aria.utils.console`
+-------------------------
+
+.. automodule:: aria.utils.console
+
+:mod:`aria.utils.exceptions`
+----------------------------
+
+.. automodule:: aria.utils.exceptions
+
+:mod:`aria.utils.file`
+----------------------
+
+.. automodule:: aria.utils.file
+
+:mod:`aria.utils.formatting`
+----------------------------
+
+.. automodule:: aria.utils.formatting
+
+:mod:`aria.utils.http`
+----------------------
+
+.. automodule:: aria.utils.http
+
+:mod:`aria.utils.imports`
+-------------------------
+
+.. automodule:: aria.utils.imports
+
+:mod:`aria.utils.openclose`
+---------------------------
+
+.. automodule:: aria.utils.openclose
+
+:mod:`aria.utils.plugin`
+------------------------
+
+.. automodule:: aria.utils.plugin
+
+:mod:`aria.utils.process`
+-------------------------
+
+.. automodule:: aria.utils.process
+
+:mod:`aria.utils.specification`
+-------------------------------
+
+.. automodule:: aria.utils.specification
+
+:mod:`aria.utils.threading`
+---------------------------
+
+.. automodule:: aria.utils.threading
+
+:mod:`aria.utils.type`
+----------------------
+
+.. automodule:: aria.utils.type
+
+:mod:`aria.utils.uris`
+----------------------
+
+.. automodule:: aria.utils.uris
+
+:mod:`aria.utils.uuid`
+----------------------
+
+.. automodule:: aria.utils.uuid
+
+:mod:`aria.utils.validation`
+----------------------------
+
+.. automodule:: aria.utils.validation
+
+:mod:`aria.utils.versions`
+--------------------------
+
+.. automodule:: aria.utils.versions

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria_extension_tosca.simple_nfv_v1_0.rst
----------------------------------------------------------------------
diff --git a/docs/aria_extension_tosca.simple_nfv_v1_0.rst b/docs/aria_extension_tosca.simple_nfv_v1_0.rst
new file mode 100644
index 0000000..6e7b6cd
--- /dev/null
+++ b/docs/aria_extension_tosca.simple_nfv_v1_0.rst
@@ -0,0 +1,20 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria_extension_tosca.simple_nfv_v1_0`
+===========================================
+
+.. automodule:: aria_extension_tosca.simple_nfv_v1_0

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria_extension_tosca.simple_v1_0.modeling.rst
----------------------------------------------------------------------
diff --git a/docs/aria_extension_tosca.simple_v1_0.modeling.rst b/docs/aria_extension_tosca.simple_v1_0.modeling.rst
new file mode 100644
index 0000000..8bc5499
--- /dev/null
+++ b/docs/aria_extension_tosca.simple_v1_0.modeling.rst
@@ -0,0 +1,75 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling`
+================================================
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.artifacts`
+----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.artifacts
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.capabilities`
+-------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.capabilities
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.constraints`
+------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.constraints
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.copy`
+-----------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.copy
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.data_types`
+-----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.data_types
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.functions`
+----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.functions
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.interfaces`
+-----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.interfaces
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.parameters`
+-----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.parameters
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.policies`
+---------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.policies
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.requirements`
+-------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.requirements
+
+:mod:`aria_extension_tosca.simple_v1_0.modeling.substitution_mappings`
+----------------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.modeling.substitution_mappings

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria_extension_tosca.simple_v1_0.presentation.rst
----------------------------------------------------------------------
diff --git a/docs/aria_extension_tosca.simple_v1_0.presentation.rst b/docs/aria_extension_tosca.simple_v1_0.presentation.rst
new file mode 100644
index 0000000..964c029
--- /dev/null
+++ b/docs/aria_extension_tosca.simple_v1_0.presentation.rst
@@ -0,0 +1,40 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria_extension_tosca.simple_v1_0.presentation`
+====================================================
+
+.. automodule:: aria_extension_tosca.simple_v1_0.presentation
+
+:mod:`aria_extension_tosca.simple_v1_0.presentation.extensible`
+---------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.presentation.extensible
+
+:mod:`aria_extension_tosca.simple_v1_0.presentation.field_getters`
+------------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.presentation.field_getters
+
+:mod:`aria_extension_tosca.simple_v1_0.presentation.field_validators`
+---------------------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.presentation.field_validators
+
+:mod:`aria_extension_tosca.simple_v1_0.presentation.types`
+----------------------------------------------------------
+
+.. automodule:: aria_extension_tosca.simple_v1_0.presentation.types

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/aria_extension_tosca.simple_v1_0.rst
----------------------------------------------------------------------
diff --git a/docs/aria_extension_tosca.simple_v1_0.rst b/docs/aria_extension_tosca.simple_v1_0.rst
new file mode 100644
index 0000000..bdae6ab
--- /dev/null
+++ b/docs/aria_extension_tosca.simple_v1_0.rst
@@ -0,0 +1,20 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+:mod:`aria_extension_tosca.simple_v1_0`
+=======================================
+
+.. automodule:: aria_extension_tosca.simple_v1_0

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/cli.rst
----------------------------------------------------------------------
diff --git a/docs/cli.rst b/docs/cli.rst
new file mode 100644
index 0000000..ee51545
--- /dev/null
+++ b/docs/cli.rst
@@ -0,0 +1,57 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+CLI
+===
+
+.. click:: aria.cli.main:_aria
+   :prog: aria
+
+.. click:: aria.cli.commands.reset:reset
+   :prog: aria reset
+   :show-nested:
+
+.. click:: aria.cli.commands.plugins:plugins
+   :prog: aria plugins
+   :show-nested:
+
+.. click:: aria.cli.commands.service_templates:service_templates
+   :prog: aria service_templates
+   :show-nested:
+
+.. click:: aria.cli.commands.node_templates:node_templates
+   :prog: aria node_templates
+   :show-nested:
+
+.. click:: aria.cli.commands.services:services
+   :prog: aria services
+   :show-nested:
+
+.. click:: aria.cli.commands.nodes:nodes
+   :prog: aria nodes
+   :show-nested:
+
+.. click:: aria.cli.commands.workflows:workflows
+   :prog: aria workflows
+   :show-nested:
+
+.. click:: aria.cli.commands.executions:executions
+   :prog: aria executions
+   :show-nested:
+
+.. click:: aria.cli.commands.logs:logs
+   :prog: aria logs
+   :show-nested:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/conf.py
----------------------------------------------------------------------
diff --git a/docs/conf.py b/docs/conf.py
index e557f02..6361621 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -15,7 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# ARIA documentation build configuration file.
+# ARIA TOSCA documentation build configuration file.
 #
 # This file is execfile()d with the current directory set to its
 # containing dir.
@@ -48,7 +48,12 @@ with open('../VERSION') as f:
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = ['sphinx.ext.autodoc']
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.autosummary',
+    'sphinx.ext.intersphinx',
+    'sphinx_click.ext'
+]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -67,9 +72,9 @@ source_suffix = '.rst'
 master_doc = 'index'
 
 # General information about the project.
-project = u'ARIA'
-copyright = u'2016, Apache Software Foundation' # @ReservedAssignment
-author = u'ARIA'
+project = u'ARIA TOSCA'
+copyright = u'2016-2017, Apache Software Foundation' # @ReservedAssignment
+author = u'Apache Software Foundation'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -152,7 +157,7 @@ html_theme = 'sphinx_rtd_theme'
 # The name for this set of Sphinx documents.
 # "<project> v<release> documentation" by default.
 #
-# html_title = u'ARIA v0.1.0'
+# html_title = u'ARIA TOSCA v0.1.0'
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
 #
@@ -252,7 +257,7 @@ html_static_path = ['_static']
 # html_search_scorer = 'scorer.js'
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'ARIAdoc'
+htmlhelp_basename = 'ARIATOSCAdoc'
 
 # -- Options for LaTeX output ---------------------------------------------
 
@@ -278,7 +283,7 @@ latex_elements = {
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-    (master_doc, 'ARIA.tex', u'ARIA',
+    (master_doc, 'ARIATOSCA.tex', u'ARIA TOSCA',
      u'Apache Software Foundation', 'manual'),
 ]
 
@@ -314,7 +319,7 @@ latex_documents = [
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    (master_doc, 'aria', u'ARIA',
+    (master_doc, 'aria', u'ARIA TOSCA',
      [author], 1)
 ]
 
@@ -329,8 +334,9 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    (master_doc, 'ARIA', u'ARIA',
-     author, 'ARIA', 'Toolkit for parsing TOSCA.',
+    (master_doc, 'ARIATOSCA', u'ARIA TOSCA',
+     author, 'ARIA TOSCA', 'an open, light, CLI-driven library of orchestration tools that other '
+     'open projects can consume to easily build TOSCA-based orchestration solutions.',
      'Miscellaneous'),
 ]
 
@@ -350,19 +356,61 @@ texinfo_documents = [
 #
 # texinfo_no_detailmenu = False
 
+
+# -- Options for InterSphinx
+
+intersphinx_mapping = {
+    'python': ('https://docs.python.org/2.7', None)
+}
+
 # -- Options for Python domain
 
-# Include __init__ docstring into class docstring
+# Append __init__ docstring into class docstring
 autoclass_content = 'both'
 
 # Default to everything important
-autodoc_default_flags = ['members', 'undoc-members', 'show-inheritance']
+autodoc_default_flags = [
+    'members',
+    'undoc-members',
+    'show-inheritance'
+]
 
-def on_skip_members(app, what, name, obj, skip, options):
-    if not skip:
-        if name in ('FIELDS', 'ALLOW_UNKNOWN_FIELDS', 'SHORT_FORM_FIELD'):
-            skip = True
+SKIP_MEMBERS = (
+    'FIELDS',
+    'ALLOW_UNKNOWN_FIELDS',
+    'SHORT_FORM_FIELD',
+    'INSTRUMENTATION_FIELDS'
+)
+
+SKIP_MEMBER_SUFFIXES = (
+    '_fk',
+)
+
+NEVER_SKIP_MEMBERS = (
+    '__evaluate__',
+)
+
+# 'autodoc-skip-member' event
+def on_skip_member(app, what, name, obj, skip, options):
+    if name in NEVER_SKIP_MEMBERS:
+        return False
+    if name in SKIP_MEMBERS: 
+        return True
+    for suffix in SKIP_MEMBER_SUFFIXES:
+        if name.endswith(suffix):
+            return True
     return skip
-    
+
+from sphinx.domains.python import PythonDomain
+
+class PatchedPythonDomain(PythonDomain):
+    # See: https://github.com/sphinx-doc/sphinx/issues/3866
+    def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+        if 'refspecific' in node:
+            del node['refspecific']
+        return super(PatchedPythonDomain, self).resolve_xref(
+            env, fromdocname, builder, typ, target, node, contnode)
+
 def setup(app):
-    app.connect('autodoc-skip-member', on_skip_members)
+    app.connect('autodoc-skip-member', on_skip_member)
+    app.override_domain(PatchedPythonDomain)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/index.rst
----------------------------------------------------------------------
diff --git a/docs/index.rst b/docs/index.rst
index d915ae6..f68769b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,24 +14,68 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 
+User Manual for ARIA TOSCA
+==========================
 
-ARIA API
-========
+`ARIA TOSCA <http://ariatosca.incubator.apache.org/>`__ is an open, light, CLI-driven library of
+orchestration tools that other open projects can consume to easily build
+`TOSCA <https://www.oasis-open.org/committees/tosca/>`__-based orchestration solutions. ARIA is now
+an incubation project at the Apache Software Foundation.  
 
-`ARIA (Agile Reference Implementation of Automation) <http://ariatosca.org/>`__  is a an open,
-light, CLI-driven library of orchestration tools that other open projects can consume to easily
-build `TOSCA <https://www.oasis-open.org/committees/tosca/>`__-based orchestration solutions. It
-supports NFV and hybrid cloud scenarios.
+Interfaces
+----------
 
+.. toctree::
+   :maxdepth: 1
+   :includehidden:
+
+   cli
+   rest
+
+SDK
+---
+
+Core
+####
+
+.. toctree::
+   :maxdepth: 1
+   :includehidden:
+
+   aria
+   aria.cli
+   aria.modeling
+   aria.modeling.models
+   aria.orchestrator
+   aria.orchestrator.context
+   aria.orchestrator.execution_plugin
+   aria.orchestrator.execution_plugin.ctx_proxy
+   aria.orchestrator.execution_plugin.ssh
+   aria.orchestrator.workflows
+   aria.orchestrator.workflows.api
+   aria.orchestrator.workflows.builtin
+   aria.orchestrator.workflows.executor
+   aria.parser
+   aria.parser.consumption
+   aria.parser.loading
+   aria.parser.modeling
+   aria.parser.presentation
+   aria.parser.reading
+   aria.parser.validation
+   aria.storage
+   aria.utils
 
-Packages
---------
+Extensions
+##########
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
+   :includehidden:
 
-   parser
-   tosca
+   aria_extension_tosca.simple_v1_0
+   aria_extension_tosca.simple_v1_0.modeling
+   aria_extension_tosca.simple_v1_0.presentation
+   aria_extension_tosca.simple_nfv_v1_0
 
 
 Indices and Tables

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/parser.rst
----------------------------------------------------------------------
diff --git a/docs/parser.rst b/docs/parser.rst
deleted file mode 100644
index 5db02e2..0000000
--- a/docs/parser.rst
+++ /dev/null
@@ -1,56 +0,0 @@
-..
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-   
-       http://www.apache.org/licenses/LICENSE-2.0
-   
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-`aria.parser` Package
-#####################
-
-This is the core parser API.
-
-:mod:`aria.parser`
-******************
-
-.. automodule:: aria
-
-:mod:`aria.parser.consumption`
-******************************
-
-.. automodule:: aria.parser.consumption
-
-:mod:`aria.parser.modeling`
-***************************
-
-.. automodule:: aria.parser.modeling
-
-:mod:`aria.parser.loading`
-**************************
-
-.. automodule:: aria.parser.loading
-
-:mod:`aria.parser.presentation`
-*******************************
-
-.. automodule:: aria.parser.presentation
-
-:mod:`aria.parser.reading`
-**************************
-
-.. automodule:: aria.parser.reading
-
-:mod:`aria.parser.validation`
-*****************************
-
-.. automodule:: aria.parser.validation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/requirements.txt
----------------------------------------------------------------------
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 976c5b6..a49bb26 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -11,4 +11,5 @@
 # limitations under the License.
 
 Sphinx>=1.6.2, <2.0.0
-sphinx_rtd_theme>=0.2.4, <1.0.0
+sphinx_rtd_theme>=0.2.4, <2.0.0
+sphinx-click>=1.0.2, <1.1.0

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/rest.rst
----------------------------------------------------------------------
diff --git a/docs/rest.rst b/docs/rest.rst
new file mode 100644
index 0000000..185837e
--- /dev/null
+++ b/docs/rest.rst
@@ -0,0 +1,20 @@
+..
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+   
+       http://www.apache.org/licenses/LICENSE-2.0
+   
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+REST
+====
+
+TODO

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/docs/tosca.rst
----------------------------------------------------------------------
diff --git a/docs/tosca.rst b/docs/tosca.rst
deleted file mode 100644
index c98a4a9..0000000
--- a/docs/tosca.rst
+++ /dev/null
@@ -1,36 +0,0 @@
-..
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-   
-       http://www.apache.org/licenses/LICENSE-2.0
-   
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-`aria_extension_tosca` Package
-##############################
-
-This is the ARIA TOSCA extension.
-
-:mod:`aria_extension_tosca`
-***************************
-
-.. automodule:: aria_extension_tosca
-
-:mod:`aria_extension_tosca.simple_v1_0`
-***************************************
-
-.. automodule:: aria_extension_tosca.simple_v1_0
-
-:mod:`aria_extension_tosca.simple_nfv_v1_0`
-*******************************************
-
-.. automodule:: aria_extension_tosca.simple_nfv_v1_0

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
index cd07f42..64178aa 100644
--- a/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
+++ b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
@@ -21,12 +21,12 @@ from ..simple_v1_0 import ToscaSimplePresenter1_0
 
 class ToscaSimpleNfvPresenter1_0(ToscaSimplePresenter1_0): # pylint: disable=invalid-name,abstract-method
     """
-    ARIA presenter for the `TOSCA Simple Profile for NFV v1.0 csd03 <http://docs.oasis-open.org
-    /tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html>`__.
+    ARIA presenter for the `TOSCA Simple Profile for NFV v1.0 csd04 <http://docs.oasis-open.org
+    /tosca/tosca-nfv/v1.0/csd04/tosca-nfv-v1.0-csd04.html>`__.
 
-    Supported :code:`tosca_definitions_version` values:
+    Supported ``tosca_definitions_version`` values:
 
-    * :code:`tosca_simple_profile_for_nfv_1_0`
+    * ``tosca_simple_profile_for_nfv_1_0``
     """
 
     DSL_VERSIONS = ('tosca_simple_profile_for_nfv_1_0',)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/__init__.py
index 7dcc60a..61995db 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/__init__.py
@@ -13,6 +13,115 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+Parser implementation of `TOSCA Simple Profile v1.0 cos01 <http://docs.oasis-open.org/tosca
+/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html>`__.
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.ToscaSimplePresenter1_0
+
+Assignments
+-----------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.PropertyAssignment
+   aria_extension_tosca.simple_v1_0.OperationAssignment
+   aria_extension_tosca.simple_v1_0.InterfaceAssignment
+   aria_extension_tosca.simple_v1_0.RelationshipAssignment
+   aria_extension_tosca.simple_v1_0.RequirementAssignment
+   aria_extension_tosca.simple_v1_0.AttributeAssignment
+   aria_extension_tosca.simple_v1_0.CapabilityAssignment
+   aria_extension_tosca.simple_v1_0.ArtifactAssignment
+
+Definitions
+-----------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.PropertyDefinition
+   aria_extension_tosca.simple_v1_0.AttributeDefinition
+   aria_extension_tosca.simple_v1_0.ParameterDefinition
+   aria_extension_tosca.simple_v1_0.OperationDefinition
+   aria_extension_tosca.simple_v1_0.InterfaceDefinition
+   aria_extension_tosca.simple_v1_0.RelationshipDefinition
+   aria_extension_tosca.simple_v1_0.RequirementDefinition
+   aria_extension_tosca.simple_v1_0.CapabilityDefinition
+
+Filters
+-------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.CapabilityFilter
+   aria_extension_tosca.simple_v1_0.NodeFilter
+
+Miscellaneous
+-------------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.Description
+   aria_extension_tosca.simple_v1_0.MetaData
+   aria_extension_tosca.simple_v1_0.Repository
+   aria_extension_tosca.simple_v1_0.Import
+   aria_extension_tosca.simple_v1_0.ConstraintClause
+   aria_extension_tosca.simple_v1_0.EntrySchema
+   aria_extension_tosca.simple_v1_0.OperationImplementation
+   aria_extension_tosca.simple_v1_0.SubstitutionMappingsRequirement
+   aria_extension_tosca.simple_v1_0.SubstitutionMappingsCapability
+   aria_extension_tosca.simple_v1_0.SubstitutionMappings
+
+Templates
+---------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.NodeTemplate
+   aria_extension_tosca.simple_v1_0.RelationshipTemplate
+   aria_extension_tosca.simple_v1_0.GroupTemplate
+   aria_extension_tosca.simple_v1_0.PolicyTemplate
+   aria_extension_tosca.simple_v1_0.TopologyTemplate
+   aria_extension_tosca.simple_v1_0.ServiceTemplate
+
+Types
+-----
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.ArtifactType
+   aria_extension_tosca.simple_v1_0.DataType
+   aria_extension_tosca.simple_v1_0.CapabilityType
+   aria_extension_tosca.simple_v1_0.InterfaceType
+   aria_extension_tosca.simple_v1_0.RelationshipType
+   aria_extension_tosca.simple_v1_0.NodeType
+   aria_extension_tosca.simple_v1_0.GroupType
+   aria_extension_tosca.simple_v1_0.PolicyType
+
+Data types
+----------
+
+.. autosummary::
+   :nosignatures:
+
+   aria_extension_tosca.simple_v1_0.Timestamp
+   aria_extension_tosca.simple_v1_0.Version
+   aria_extension_tosca.simple_v1_0.Range
+   aria_extension_tosca.simple_v1_0.List
+   aria_extension_tosca.simple_v1_0.Map
+   aria_extension_tosca.simple_v1_0.ScalarSize
+   aria_extension_tosca.simple_v1_0.ScalarTime
+   aria_extension_tosca.simple_v1_0.ScalarFrequency
+"""
+
 from .presenter import ToscaSimplePresenter1_0
 from .assignments import (PropertyAssignment, OperationAssignment, InterfaceAssignment,
                           RelationshipAssignment, RequirementAssignment, AttributeAssignment,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/3f09ecde/extensions/aria_extension_tosca/simple_v1_0/assignments.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/assignments.py b/extensions/aria_extension_tosca/simple_v1_0/assignments.py
index 79f6377..0590527 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/assignments.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/assignments.py
@@ -61,7 +61,7 @@ class OperationAssignment(ExtensiblePresentation):
         """
         The optional description string for the associated named operation.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @object_field(OperationImplementation)
@@ -70,7 +70,7 @@ class OperationAssignment(ExtensiblePresentation):
         The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR
         file).
 
-        :rtype: :class:`OperationImplementation`
+        :type: :class:`OperationImplementation`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -81,7 +81,7 @@ class OperationAssignment(ExtensiblePresentation):
         when operation definitions are included as part of a Requirement assignment in a Node
         Template.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @cachedmethod
@@ -124,13 +124,13 @@ class InterfaceAssignment(ExtensiblePresentation):
         when interface definitions are referenced as part of a Requirement assignment in a Node
         Template.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @object_dict_unknown_fields(OperationAssignment)
     def operations(self):
         """
-        :rtype: dict of str, :class:`OperationAssignment`
+        :type: {:obj:`basestring`: :class:`OperationAssignment`}
         """
 
     @cachedmethod
@@ -157,6 +157,10 @@ class InterfaceAssignment(ExtensiblePresentation):
 @short_form_field('type')
 @has_fields
 class RelationshipAssignment(ExtensiblePresentation):
+    """
+    Relationship assignment.
+    """
+
     @field_validator(relationship_template_or_type_validator)
     @primitive_field(str)
     def type(self):
@@ -164,7 +168,7 @@ class RelationshipAssignment(ExtensiblePresentation):
         The optional reserved keyname used to provide the name of the Relationship Type for the
         requirement assignment's relationship keyname.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -172,7 +176,7 @@ class RelationshipAssignment(ExtensiblePresentation):
         """
         ARIA NOTE: This field is not mentioned in the spec, but is implied.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @object_dict_field(InterfaceAssignment)
@@ -182,7 +186,7 @@ class RelationshipAssignment(ExtensiblePresentation):
         the corresponding Relationship Type in order to provide Property assignments for these
         interfaces or operations of these interfaces.
 
-        :rtype: dict of str, :class:`InterfaceAssignment`
+        :type: {:obj:`basestring`: :class:`InterfaceAssignment`}
         """
 
     @cachedmethod
@@ -224,7 +228,7 @@ class RequirementAssignment(ExtensiblePresentation):
         * Capability Type that the provider will use to select a type-compatible target node
           template to fulfill the requirement at runtime.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_validator(node_template_or_type_validator)
@@ -238,7 +242,7 @@ class RequirementAssignment(ExtensiblePresentation):
         * Node Type name that the provider will use to select a type-compatible node template to
           fulfill the requirement at runtime.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(RelationshipAssignment)
@@ -251,7 +255,7 @@ class RequirementAssignment(ExtensiblePresentation):
         * Relationship Type that the provider will use to select a type-compatible relationship
           template to relate the source node to the target node at runtime.
 
-        :rtype: :class:`RelationshipAssignment`
+        :type: :class:`RelationshipAssignment`
         """
 
     @field_validator(node_filter_validator)
@@ -261,7 +265,7 @@ class RequirementAssignment(ExtensiblePresentation):
         The optional filter definition that TOSCA orchestrators or providers would use to select a
         type-compatible target node that can fulfill the associated abstract requirement at runtime.
 
-        :rtype: :class:`NodeFilter`
+        :type: :class:`NodeFilter`
         """
 
     @cachedmethod
@@ -325,7 +329,7 @@ class CapabilityAssignment(ExtensiblePresentation):
         """
         An optional list of property definitions for the Capability definition.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @object_dict_field(AttributeAssignment)
@@ -333,7 +337,7 @@ class CapabilityAssignment(ExtensiblePresentation):
         """
         An optional list of attribute definitions for the Capability definition.
 
-        :rtype: dict of str, :class:`AttributeAssignment`
+        :type: {:obj:`basestring`: :class:`AttributeAssignment`}
         """
 
     @cachedmethod
@@ -370,7 +374,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         """
         The required artifact type for the artifact definition.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @primitive_field(str, required=True)
@@ -379,7 +383,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         The required URI string (relative or absolute) which can be used to locate the artifact's
         file.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @field_validator(type_validator('repository', 'repositories'))
@@ -390,7 +394,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         repository that contains the artifact. The artifact is expected to be referenceable by its
         file URI within the repository.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_field(Description)
@@ -398,7 +402,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         """
         The optional description for the artifact definition.
 
-        :rtype: :class:`Description`
+        :type: :class:`Description`
         """
 
     @primitive_field(str)
@@ -406,7 +410,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         """
         The file path the associated file would be deployed into within the target node's container.
 
-        :rtype: str
+        :type: :obj:`basestring`
         """
 
     @object_dict_field(PropertyAssignment)
@@ -414,7 +418,7 @@ class ArtifactAssignment(ExtensiblePresentation):
         """
         ARIA NOTE: This field is not mentioned in the spec, but is implied.
 
-        :rtype: dict of str, :class:`PropertyAssignment`
+        :type: {:obj:`basestring`: :class:`PropertyAssignment`}
         """
 
     @cachedmethod