ariatosca-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From emblempar...@apache.org
Subject [3/3] incubator-ariatosca git commit: Full documentation of models; fix to subtitution
Date Wed, 28 Jun 2017 02:50:22 GMT
Full documentation of models; fix to subtitution


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

Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 4ebbbb15664a09d80088cf82e8d3c3f1ee6fde62
Parents: 7ed92d0
Author: Tal Liron <tal.liron@gmail.com>
Authored: Tue Jun 27 21:49:59 2017 -0500
Committer: Tal Liron <tal.liron@gmail.com>
Committed: Tue Jun 27 21:49:59 2017 -0500

----------------------------------------------------------------------
 aria/cli/inputs.py                              |   16 +-
 aria/cli/service_template_utils.py              |    2 +-
 aria/cli/table.py                               |   16 +-
 aria/cli/utils.py                               |   16 +-
 aria/logger.py                                  |    2 +-
 aria/modeling/functions.py                      |    4 +-
 aria/modeling/mixins.py                         |   45 +-
 aria/modeling/models.py                         |   19 +-
 aria/modeling/orchestration.py                  |  591 ++++---
 aria/modeling/service_changes.py                |   57 +-
 aria/modeling/service_common.py                 |  395 +++--
 aria/modeling/service_instance.py               | 1465 ++++++++++-------
 aria/modeling/service_template.py               | 1508 +++++++++++-------
 aria/modeling/types.py                          |    2 +-
 aria/modeling/utils.py                          |    6 +-
 aria/parser/loading/context.py                  |    2 +-
 aria/parser/presentation/presentation.py        |    4 +-
 aria/utils/caching.py                           |    2 +-
 aria/utils/collections.py                       |   17 +-
 docs/aria.modeling.models.rst                   |    1 +
 docs/conf.py                                    |   26 +-
 .../simple_v1_0/modeling/__init__.py            |    2 -
 .../orchestrator/workflows/core/test_events.py  |    4 +-
 23 files changed, 2560 insertions(+), 1642 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/inputs.py
----------------------------------------------------------------------
diff --git a/aria/cli/inputs.py b/aria/cli/inputs.py
index 11f70a0..bea3e1a 100644
--- a/aria/cli/inputs.py
+++ b/aria/cli/inputs.py
@@ -29,14 +29,14 @@ 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``)
+    :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/4ebbbb15/aria/cli/service_template_utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/service_template_utils.py b/aria/cli/service_template_utils.py
index abfbf9a..5312522 100644
--- a/aria/cli/service_template_utils.py
+++ b/aria/cli/service_template_utils.py
@@ -41,7 +41,7 @@ def get(source, service_template_filename):
     :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)
+     with CSAR archives, this is read from the metadata file)
     :type service_template_filename: basestring
     :return: path to main service template file
     :rtype: basestring

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/table.py
----------------------------------------------------------------------
diff --git a/aria/cli/table.py b/aria/cli/table.py
index a4e959c..74487ae 100644
--- a/aria/cli/table.py
+++ b/aria/cli/table.py
@@ -33,16 +33,15 @@ def print_data(columns, items, header_text,
     :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'}]``
+     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}``
+     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
-    :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'}``
+     ``{'serviceId':'123'}``
     :type defaults: {:obj:`basestring`: :obj:`basestring`}
     """
     if items is None:
@@ -68,14 +67,13 @@ def _generate(cols, data, column_formatters=None, defaults=None):
     :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'}]``
+     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}``
+     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'}``
+     ``{'serviceId':'123'}``
     :type defaults: {:obj:`basestring`: :obj:`basestring`}
     """
     def get_values_per_column(column, row_data):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/utils.py b/aria/cli/utils.py
index 0d0666b..697ff37 100644
--- a/aria/cli/utils.py
+++ b/aria/cli/utils.py
@@ -80,8 +80,8 @@ def generate_progress_handler(file_path, action='', max_bar_length=80):
     :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)
@@ -105,16 +105,12 @@ def generate_progress_handler(file_path, action='', max_bar_length=80):
         :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/4ebbbb15/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index 2ccff25..3b01e48 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -125,7 +125,7 @@ def create_sqla_log_handler(model, log_cls, execution_id, level=logging.DEBUG):
 class _DefaultConsoleFormat(logging.Formatter):
     """
     Info level log format: ``%(message)s``
-    
+
     Every other log level is formatted: ``%(levelname)s: %(message)s``
     """
     def format(self, record):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index b764aa8..6544adf 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -42,7 +42,7 @@ class Function(object):
 
         :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``) 
+         return ``None``)
         """
 
         raise NotImplementedError
@@ -55,7 +55,7 @@ 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

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index e707f02..aafc1e9 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -99,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):
@@ -150,21 +159,22 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
 
     This model can be used as the ``container_holder`` argument for
     :func:`~aria.modeling.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
     """
 
     __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
@@ -189,7 +199,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         *All* parameters should have an owner model.
 
         :raises exceptions.ValueError: if failed to find an owner, which signifies an abnormal,
-                                       orphaned parameter
+         orphaned parameter
         """
 
         # Find first non-null relationship
@@ -214,7 +224,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         *All* parameters should have a container model.
 
         :raises exceptions.ValueError: if failed to find a container model, which signifies an
-                                       abnormal, orphaned parameter
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -260,7 +270,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         not contained in a service.
 
         :raises exceptions.ValueError: if failed to find a container model, which signifies an
-                                       abnormal, orphaned parameter
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -279,7 +289,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
         ``None`` if not contained in a service template.
 
         :raises exceptions.ValueError: if failed to find a container model, which signifies an
-                                       abnormal, orphaned parameter
+         abnormal, orphaned parameter
         """
 
         from . import models
@@ -355,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/4ebbbb15/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index 129b5bb..f2aa1ea 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -31,15 +31,15 @@ from . import (
     service_changes,
     service_common,
     orchestration,
-    mixins,
+    mixins
 )
 
+
 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
@@ -93,16 +93,25 @@ __all__ = (
 )
 
 
+def _clean_init_doc(cls):
+    # 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
+    return cls
+
+
 def _fix_doc(cls):
+    # Use the last base class's docstring
     cls.__doc__ = cls.__bases__[-1].__doc__
-    return cls
+    return _clean_init_doc(cls)
 
 
 # region service template models
 
 @_fix_doc
 class ServiceTemplate(aria_declarative_base, service_template.ServiceTemplateBase):
-    #__doc__ = service_template.ServiceTemplateBase.__doc__
     name = Column(Text, index=True, unique=True)
 
 
@@ -249,7 +258,6 @@ class ServiceModification(aria_declarative_base, service_changes.ServiceModifica
 
 # region common service models
 
-
 @_fix_doc
 class Input(aria_declarative_base, service_common.InputBase):
     pass
@@ -313,7 +321,6 @@ class Log(aria_declarative_base, orchestration.LogBase):
 class Argument(aria_declarative_base, orchestration.ArgumentBase):
     pass
 
-
 # endregion
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 6096fcc..1c94966 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -44,7 +44,7 @@ from . import (
 
 class ExecutionBase(mixins.ModelMixin):
     """
-    Execution model representation.
+    Workflow execution.
     """
 
     __tablename__ = 'execution'
@@ -69,56 +69,47 @@ 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
-
-    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)
-
-    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
+    # region one_to_many relationships
 
     @declared_attr
-    def logs(cls):
-        return relationship.one_to_many(cls, 'log')
+    def inputs(cls):
+        """
+        Execution parameters.
 
-    @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service')
+        :type: {:obj:`basestring`: :class:`Input`}
+        """
+        return relationship.one_to_many(cls, 'input', dict_key='name')
 
     @declared_attr
     def tasks(cls):
+        """
+        Tasks.
+
+        :type: [:class:`Task`]
+        """
         return relationship.one_to_many(cls, 'task')
 
     @declared_attr
-    def inputs(cls):
-        return relationship.one_to_many(cls, 'input', dict_key='name')
+    def logs(cls):
+        """
+        General log messages for the execution (not for its tasks).
 
-    # region foreign keys
+        :type: [:class:`Log`]
+        """
+        return relationship.one_to_many(cls, 'log')
+
+    # endregion
+
+    # region many_to_one relationships
 
     @declared_attr
-    def service_fk(cls):
-        return relationship.foreign_key('service')
+    def service(cls):
+        """
+        Associated service.
+
+        :type: :class:`Service`
+        """
+        return relationship.many_to_one(cls, 'service')
 
     # endregion
 
@@ -141,73 +132,78 @@ class ExecutionBase(mixins.ModelMixin):
 
     # endregion
 
-    def __str__(self):
-        return '<{0} id=`{1}` (status={2})>'.format(
-            self.__class__.__name__,
-            getattr(self, self.name_column_name()),
-            self.status
-        )
+    # region foreign keys
+
+    @declared_attr
+    def service_fk(cls):
+        return relationship.foreign_key('service')
 
+    # endregion
 
-class PluginBase(mixins.ModelMixin):
-    """
-    An installed plugin.
+    created_at = Column(DateTime, index=True, doc="""
+    Creation timestamp.
 
-    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.
+    :type: :class:`~datetime.datetime`
+    """)
 
-    :ivar archive_name: filename (not the full path) of the wagon's archive, often with a ".wgn"
-                        extension
-    :vartype archive_name: basestring
-    :ivar distribution: name of the operating system on which the wagon was installed (e.g.
-                        "ubuntu")
-    :vartype distribution: basestring
-    :ivar distribution_release: release of the operating system on which the wagon was installed
-                                (e.g. "trusty")
-    :vartype distribution_release: basestring
-    :ivar distribution_version: version of the operating system on which the wagon was installed
-                                (e.g. "14.04")
-    :vartype distribution_version: basestring
-    :ivar package_name: 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: 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: 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: Python versions supported by all the wheels (e.g. ["py26",
-                                 "py27"])
-    :vartype supported_py_versions: [basestring]
-    :ivar wheels: 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
-    """
+    started_at = Column(DateTime, nullable=True, index=True, doc="""
+    Started timestamp.
 
-    __tablename__ = 'plugin'
+    :type: :class:`~datetime.datetime`
+    """)
 
-    @declared_attr
-    def tasks(cls):
-        return relationship.one_to_many(cls, 'task')
+    ended_at = Column(DateTime, nullable=True, index=True, doc="""
+    Ended timestamp.
+
+    :type: :class:`~datetime.datetime`
+    """)
 
-    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)
+    error = Column(Text, nullable=True, doc="""
+    Error message.
+
+    :type: :obj:`basestring`
+    """)
+
+    status = Column(Enum(*STATES, name='execution_status'), default=PENDING, doc="""
+    Status.
+
+    :type: :obj:`basestring`
+    """)
+
+    workflow_name = Column(Text, doc="""
+    Workflow name.
+
+    :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
+
+    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):
@@ -216,40 +212,14 @@ 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: node actor (optional)
-    :vartype node: Node
-    :ivar relationship: relationship actor (optional)
-    :vartype relationship: Relationship
-    :ivar plugin: implementing plugin (set to None for default execution plugin)
-    :vartype plugin: Plugin
-    :ivar function: Python path to an ``@operation`` function
-    :vartype function: basestring
-    :ivar arguments: arguments that can be used by this task
-    :vartype arguments: {:obj:`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: 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'
@@ -289,71 +259,94 @@ 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')
 
-    _api_id = Column(String)
-    _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):
+        """Required for use by SQLAlchemy queries"""
+        return 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):
+        """Required for use by SQLAlchemy queries"""
+        return 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):
+        """Required for use by SQLAlchemy queries"""
+        return 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)
 
@@ -367,24 +360,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):
@@ -451,26 +513,36 @@ class TaskBase(mixins.ModelMixin):
 
 
 class LogBase(mixins.ModelMixin):
+    """
+    Single log message.
+    """
 
     __tablename__ = 'log'
 
     __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
 
@@ -484,6 +556,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
 
@@ -492,30 +588,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/4ebbbb15/aria/modeling/service_changes.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_changes.py b/aria/modeling/service_changes.py
index 97f8643..b536443 100644
--- a/aria/modeling/service_changes.py
+++ b/aria/modeling/service_changes.py
@@ -52,18 +52,6 @@ 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
@@ -102,6 +90,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
@@ -140,14 +140,6 @@ 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
@@ -173,6 +165,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))
 
@@ -224,14 +224,6 @@ 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
@@ -250,8 +242,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/4ebbbb15/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 2ba3aa3..850a1ef 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -37,17 +37,33 @@ from . import relationship
 
 class OutputBase(ParameterMixin):
     """
-    :ivar name: name
-    :vartype name: basestring
-    :ivar type_name: type name
-    :vartype type_name: basestring
-    :ivar value: value
-    :ivar description: human-readable description
-    :vartype description: basestring
+    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
@@ -60,31 +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):
-    """
-    :ivar name: name
-    :vartype name: basestring
-    :ivar type_name: type name
-    :vartype type_name: basestring
-    :ivar value: value
-    :ivar description: human-readable description
-    :vartype description: basestring
-    """
+    @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
 
@@ -122,89 +187,167 @@ class InputBase(ParameterMixin):
 
     # endregion
 
-    # region many_to_one relationships
 
-    @declared_attr
-    def service_template(cls):
-        return relationship.many_to_one(cls, 'service_template')
+class ConfigurationBase(ParameterMixin):
+    """
+    Configuration parameter.
+    """
 
-    @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service')
+    __tablename__ = 'configuration'
+
+    # region many_to_one relationships
 
     @declared_attr
-    def interface(cls):
-        return relationship.many_to_one(cls, 'interface')
+    def operation_template(cls):
+        """
+        Containing operation template (can be ``None``).
+
+        :type: :class:`OperationTemplate`
+        """
+        return relationship.many_to_one(cls, 'operation_template')
 
     @declared_attr
     def operation(cls):
+        """
+        Containing operation (can be ``None``).
+
+        :type: :class:`Operation`
+        """
         return relationship.many_to_one(cls, 'operation')
 
-    @declared_attr
-    def interface_template(cls):
-        return relationship.many_to_one(cls, 'interface_template')
+    # endregion
+
+    # region foreign keys
 
     @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_template')
+    def operation_template_fk(cls):
+        return relationship.foreign_key('operation_template', nullable=True)
 
     @declared_attr
-    def execution(cls):
-        return relationship.many_to_one(cls, 'execution')
+    def operation_fk(cls):
+        return relationship.foreign_key('operation', nullable=True)
 
     # endregion
 
 
-class ConfigurationBase(ParameterMixin):
+class PropertyBase(ParameterMixin):
     """
-    :ivar name: name
-    :vartype name: basestring
-    :ivar type_name: type name
-    :vartype type_name: basestring
-    :ivar value: value
-    :ivar description: human-readable description
-    :vartype description: basestring
+    Property parameter or declaration for a property parameter.
     """
 
-    __tablename__ = 'configuration'
+    __tablename__ = 'property'
 
-    # region foreign keys
+    # region many_to_one relationships
 
     @declared_attr
-    def operation_template_fk(cls):
-        return relationship.foreign_key('operation_template', nullable=True)
+    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_fk(cls):
-        return relationship.foreign_key('operation', nullable=True)
+    def group_template(cls):
+        """
+        Containing group template (can be ``None``).
 
-    # endregion
+        :type: :class:`GroupTemplate`
+        """
+        return relationship.many_to_one(cls, 'group_template')
 
-    # region many_to_one relationships
+    @declared_attr
+    def policy_template(cls):
+        """
+        Containing policy template (can be ``None``).
+
+        :type: :class:`PolicyTemplate`
+        """
+        return relationship.many_to_one(cls, 'policy_template')
 
     @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_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 operation(cls):
-        return relationship.many_to_one(cls, 'operation')
+    def capability_template(cls):
+        """
+        Containing capability template (can be ``None``).
 
-    # endregion
+        :type: :class:`CapabilityTemplate`
+        """
+        return relationship.many_to_one(cls, 'capability_template')
 
+    @declared_attr
+    def artifact_template(cls):
+        """
+        Containing artifact template (can be ``None``).
 
-class PropertyBase(ParameterMixin):
-    """
-    :ivar name: name
-    :vartype name: basestring
-    :ivar type_name: type name
-    :vartype type_name: basestring
-    :ivar value: value
-    :ivar description: human-readable description
-    :vartype description: basestring
-    """
+        :type: :class:`ArtifactTemplate`
+        """
+        return relationship.many_to_one(cls, 'artifact_template')
 
-    __tablename__ = 'property'
+    @declared_attr
+    def node(cls):
+        """
+        Containing node (can be ``None``).
+
+        :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 policy(cls):
+        """
+        Containing policy (can be ``None``).
+
+        :type: :class:`Policy`
+        """
+        return relationship.many_to_one(cls, 'policy')
+
+    @declared_attr
+    def relationship(cls):
+        """
+        Containing relationship (can be ``None``).
+
+        :type: :class:`Relationship`
+        """
+        return relationship.many_to_one(cls, 'relationship')
+
+    @declared_attr
+    def capability(cls):
+        """
+        Containing capability (can be ``None``).
+
+        :type: :class:`Capability`
+        """
+        return relationship.many_to_one(cls, 'capability')
+
+    @declared_attr
+    def artifact(cls):
+        """
+        Containing artifact (can be ``None``).
+
+        :type: :class:`Artifact`
+        """
+        return relationship.many_to_one(cls, 'artifact')
+
+    # endregion
 
     # region foreign keys
 
@@ -258,72 +401,36 @@ class PropertyBase(ParameterMixin):
 
     # 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):
-    """
-    :ivar name: name
-    :vartype name: basestring
-    :ivar type_name: type name
-    :vartype type_name: basestring
-    :ivar value: value
-    :ivar description: human-readable description
-    :vartype description: basestring
-    """
-
-    __tablename__ = 'attribute'
-
     # region foreign keys
 
     @declared_attr
@@ -338,25 +445,10 @@ 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.
-
-    :ivar name: name
-    :vartype name: basestring
+    Type and its children. Can serve as the root for a type hierarchy.
     """
 
     __tablename__ = 'type'
@@ -364,17 +456,41 @@ class TypeBase(InstanceModelMixin):
     __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 on_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 on_to_many relationships
+
     @declared_attr
     def children(cls):
+        """
+        Children.
+
+        :type: [:class:`Type`]
+        """
         return relationship.one_to_many_self(cls, 'parent_type_fk')
 
+    # endregion
+
     # region foreign keys
 
     @declared_attr
@@ -455,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 [])
 


Mime
View raw message