Fixes

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

Branch: refs/heads/ARIA-1-parser-test-suite
Commit: 1dfb81c8aac235c5f6aa024f4916b2eefcc43463
Parents: 89b9f13
Author: Tal Liron <tal.li...@gmail.com>
Authored: Fri Nov 24 12:22:52 2017 -0600
Committer: Tal Liron <tal.li...@gmail.com>
Committed: Fri Nov 24 12:27:30 2017 -0600

----------------------------------------------------------------------
 aria/__init__.py                                |  5 +-
 aria/modeling/service_instance.py               |  2 +-
 aria/parser/consumption/presentation.py         | 50 ++++++++++++++------
 aria/parser/presentation/presentation.py        |  1 +
 aria/parser/reading/yaml.py                     | 11 +++--
 aria/utils/collections.py                       | 25 +++++++---
 .../simple_v1_0/assignments.py                  | 19 ++++----
 .../simple_v1_0/modeling/__init__.py            | 14 +++---
 .../simple_v1_0/modeling/data_types.py          |  6 +--
 .../extensions/aria_extension_tosca/conftest.py |  3 ++
 tests/mechanisms/parsing/__init__.py            | 10 +++-
 tests/mechanisms/utils.py                       | 15 ++++--
 12 files changed, 110 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/__init__.py
----------------------------------------------------------------------
diff --git a/aria/__init__.py b/aria/__init__.py
index acaf81b..980a2bb 100644
--- a/aria/__init__.py
+++ b/aria/__init__.py
@@ -57,9 +57,8 @@ def install_aria_extensions(strict=True):
         if module_name.startswith('aria_extension_'):
             loader.find_module(module_name).load_module(module_name)
     for entry_point in pkg_resources.iter_entry_points(group='aria_extension'):
-        # It should be possible to enable non strict loading - use the package
-        # that is already installed inside the environment, and forego the
-        # version demand
+        # It should be possible to enable non strict loading - use the package 
that is already
+        # installed inside the environment, and forgo the version demand
         if strict:
             entry_point.load()
         else:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py 
b/aria/modeling/service_instance.py
index b0e426c..21c1029 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -510,7 +510,7 @@ class NodeBase(InstanceModelMixin):
     @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.
+        :return: 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'

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/parser/consumption/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/presentation.py 
b/aria/parser/consumption/presentation.py
index b1f943d..0f0b380 100644
--- a/aria/parser/consumption/presentation.py
+++ b/aria/parser/consumption/presentation.py
@@ -46,19 +46,19 @@ class Read(Consumer):
 
     def consume(self):
         # Present the main location and all imports recursively
-        main, results = self._present_all()
+        main_result, all_results = self._present_all()
 
         # Merge presentations
-        main.merge(results, self.context)
+        main_result.merge(all_results, self.context)
 
         # Cache merged presentations
         if self.context.presentation.cache:
-            for result in results:
+            for result in all_results:
                 result.cache()
 
-        self.context.presentation.presenter = main.presentation
-        if main.canonical_location is not None:
-            self.context.presentation.location = main.canonical_location
+        self.context.presentation.presenter = main_result.presentation
+        if main_result.canonical_location is not None:
+            self.context.presentation.location = main_result.canonical_location
 
     def dump(self):
         if self.context.has_arg_switch('yaml'):
@@ -73,11 +73,18 @@ class Read(Consumer):
             self.context.presentation.presenter._dump(self.context)
 
     def _handle_exception(self, e):
-        if isinstance(e, _Skip):
+        if isinstance(e, _CancelPresentation):
             return
         super(Read, self)._handle_exception(e)
 
     def _present_all(self):
+        """
+        Presents all locations, including all nested imports, from the main 
location. Uses a thread
+        pool executor for best performance.
+
+        The main presentation is returned separately for easier access.
+        """
+
         location = self.context.presentation.location
 
         if location is None:
@@ -87,7 +94,7 @@ class Read(Consumer):
         executor = self.context.presentation.create_executor()
         try:
             # This call may recursively submit tasks to the executor if there 
are imports
-            main = self._present(location, None, None, executor)
+            main_result = self._present(location, None, None, executor)
 
             # Wait for all tasks to complete
             executor.drain()
@@ -96,15 +103,22 @@ class Read(Consumer):
             for e in executor.exceptions:
                 self._handle_exception(e)
 
-            results = executor.returns or []
+            all_results = executor.returns or []
         finally:
             executor.close()
 
-        results.insert(0, main)
+        all_results.insert(0, main_result)
 
-        return main, results
+        return main_result, all_results
 
     def _present(self, location, origin_canonical_location, 
origin_presenter_class, executor):
+        """
+        Presents a single location. If the location has imports, those are 
submitted to the thread
+        pool executor.
+
+        Supports a presentation cache based on the canonical location as cache 
key.
+        """
+
         # Link the context to this thread
         self.context.set_thread_local()
 
@@ -118,7 +132,7 @@ class Read(Consumer):
 
         # Skip self imports
         if canonical_location == origin_canonical_location:
-            raise _Skip()
+            raise _CancelPresentation()
 
         if self.context.presentation.cache:
             # Is the presentation in the global cache?
@@ -154,9 +168,10 @@ class Read(Consumer):
         loader = 
self.context.loading.loader_source.get_loader(self.context.loading, location,
                                                                
origin_canonical_location)
 
-        canonical_location = None
-
         if origin_canonical_location is not None:
+            # The cache key is is a combination of the canonical location of 
the origin, which is
+            # globally absolute and never changes, and our location, which 
might be relative to
+            # the origin's location
             cache_key = (origin_canonical_location, location)
             try:
                 canonical_location = CANONICAL_LOCATION_CACHE[cache_key]
@@ -210,6 +225,11 @@ class Read(Consumer):
 
 
 class _Result(object):
+    """
+    The result of a :meth:`Read._present` call. Contains the read presentation 
itself, as well as
+    extra fields to help caching and keep track of merging.
+    """
+
     def __init__(self, presentation, canonical_location, 
origin_canonical_location):
         self.presentation = presentation
         self.canonical_location = canonical_location
@@ -261,5 +281,5 @@ class _Result(object):
         PRESENTATION_CACHE[self.canonical_location] = self.presentation
 
 
-class _Skip(Exception):
+class _CancelPresentation(Exception):
     pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/parser/presentation/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/presentation.py 
b/aria/parser/presentation/presentation.py
index e1104e5..762ecba 100644
--- a/aria/parser/presentation/presentation.py
+++ b/aria/parser/presentation/presentation.py
@@ -199,6 +199,7 @@ class Presentation(PresentationBase):
     """
 
     def _validate(self, context):
+        # Allow the skipping of normative type validation (for improved 
performance)
         if (not context.presentation.configuration.get('validate_normative', 
True)) \
             and self._get_extension('normative'):
             return

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/parser/reading/yaml.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/yaml.py b/aria/parser/reading/yaml.py
index 77f8144..d843859 100644
--- a/aria/parser/reading/yaml.py
+++ b/aria/parser/reading/yaml.py
@@ -10,8 +10,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from ...utils.yaml import yaml # @UnresolvedImport
-
+from ...utils.yaml import yaml
 from ...utils.collections import OrderedDict
 from .reader import Reader
 from .locator import Locator
@@ -19,9 +18,12 @@ from .exceptions import ReaderSyntaxError
 from .locator import (LocatableString, LocatableInt, LocatableFloat)
 
 
-MERGE_TAG = u'tag:yaml.org,2002:merge'
+# YAML mapping tag
 MAP_TAG = u'tag:yaml.org,2002:map'
 
+# This is an internal tag used by ruamel.yaml for merging nodes
+MERGE_TAG = u'tag:yaml.org,2002:merge'
+
 
 # Add our types to RoundTripRepresenter
 yaml.representer.RoundTripRepresenter.add_representer(
@@ -33,6 +35,9 @@ yaml.representer.RoundTripRepresenter.add_representer(
 
 
 def construct_yaml_map(self, node):
+    """
+    Replacement for ruamel.yaml's constructor that uses OrderedDict instead of 
dict.
+    """
     data = OrderedDict()
     yield data
     value = self.construct_mapping(node)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/aria/utils/collections.py
----------------------------------------------------------------------
diff --git a/aria/utils/collections.py b/aria/utils/collections.py
index cfd8fda..2126d59 100644
--- a/aria/utils/collections.py
+++ b/aria/utils/collections.py
@@ -34,7 +34,7 @@ except ImportError:
 def cls_name(cls):
     module = str(cls.__module__)
     name = str(cls.__name__)
-    return name if module == '__builtin__' else '%s.%s' % (module, name)
+    return name if module == '__builtin__' else '{0}.{1}'.format(module, name)
 
 
 class FrozenList(list):
@@ -145,7 +145,8 @@ class StrictList(list):
 
     def _wrap(self, value):
         if (self.value_class is not None) and (not isinstance(value, 
self.value_class)):
-            raise TypeError('value must be a "%s": %s' % 
(cls_name(self.value_class), repr(value)))
+            raise TypeError('value must be a "{0}": {1}'
+                            .format(cls_name(self.value_class), repr(value)))
         if self.wrapper_function is not None:
             value = self.wrapper_function(value)
         return value
@@ -209,7 +210,8 @@ class StrictDict(OrderedDict):
 
     def __getitem__(self, key):
         if (self.key_class is not None) and (not isinstance(key, 
self.key_class)):
-            raise TypeError('key must be a "%s": %s' % 
(cls_name(self.key_class), repr(key)))
+            raise TypeError('key must be a "{0}": {1}'
+                            .format(cls_name(self.key_class), repr(key)))
         value = super(StrictDict, self).__getitem__(key)
         if self.unwrapper_function is not None:
             value = self.unwrapper_function(value)
@@ -217,9 +219,11 @@ class StrictDict(OrderedDict):
 
     def __setitem__(self, key, value, **_):
         if (self.key_class is not None) and (not isinstance(key, 
self.key_class)):
-            raise TypeError('key must be a "%s": %s' % 
(cls_name(self.key_class), repr(key)))
+            raise TypeError('key must be a "{0}": {1}'
+                            .format(cls_name(self.key_class), repr(key)))
         if (self.value_class is not None) and (not isinstance(value, 
self.value_class)):
-            raise TypeError('value must be a "%s": %s' % 
(cls_name(self.value_class), repr(value)))
+            raise TypeError('value must be a "{0}": {1}'
+                            .format(cls_name(self.value_class), repr(value)))
         if self.wrapper_function is not None:
             value = self.wrapper_function(value)
         return super(StrictDict, self).__setitem__(key, value)
@@ -228,6 +232,14 @@ class StrictDict(OrderedDict):
 def merge(dict_a, dict_b, copy=True, strict=False, path=None):
     """
     Merges dicts, recursively.
+
+    :param dict_a: target dict (will be modified)
+    :param dict_b: source dict (will not be modified)
+    :param copy: if True, will use :func:`deepcopy_fast` on each merged element
+    :param strict: if True, will raise a ValueError if there are key 
conflicts, otherwise will
+     override exiting values
+    :param path: for internal use in strict mode
+    :return: dict_a, after the merge
     """
 
     # TODO: a.add_yaml_merge(b),
@@ -244,7 +256,8 @@ def merge(dict_a, dict_b, copy=True, strict=False, 
path=None):
                 merge(value_a, value_b, copy, strict, path)
             elif value_a != value_b:
                 if strict:
-                    raise ValueError('dict merge conflict at %s' % 
'.'.join(path + [str(key)]))
+                    raise ValueError('dict merge conflict at {0}'
+                                     .format('.'.join(path + [str(key)])))
                 else:
                     dict_a[key] = deepcopy_fast(value_b) if copy else value_b
         else:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/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 55b7e8d..6248483 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/assignments.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/assignments.py
@@ -146,14 +146,12 @@ class InterfaceAssignment(ExtensiblePresentation):
 
             if isinstance(self._container._container, RequirementAssignment):
                 # In RequirementAssignment
-                requirement_definition = 
self._container._container._get_definition(context)
-                if requirement_definition is not None:
-                    relationship_definition = 
requirement_definition.relationship
-                    if relationship_definition is not None:
-                        interface_definitions = 
relationship_definition.interfaces
-                        if interface_definitions is not None:
-                            if self._name in interface_definitions:
-                                return 
interface_definitions[self._name]._get_type(context)
+                relationship_definition = \
+                    
self._container._container._get_relationship_definition(context)
+                interface_definitions = relationship_definition.interfaces \
+                    if relationship_definition is not None else None
+                if (interface_definitions is not None) and (self._name in 
interface_definitions):
+                    return interface_definitions[self._name]._get_type(context)
 
         interface_definitions = the_type._get_interfaces(context) \
             if the_type is not None else None
@@ -312,6 +310,11 @@ class RequirementAssignment(ExtensiblePresentation):
         return None
 
     @cachedmethod
+    def _get_relationship_definition(self, context):
+        requirement_definition = self._get_definition(context)
+        return requirement_definition.relationship if requirement_definition 
is not None else None
+
+    @cachedmethod
     def _get_capability(self, context):
         capability = self.capability
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/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 17b94fc..6c305c3 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -664,18 +664,18 @@ def create_constraint(context, node_filter, 
constraint_clause, property_name, ca
 
     constraint_key = constraint_clause._raw.keys()[0]
 
-    the_type = constraint_clause._get_type(context)
+    value_type = constraint_clause._get_type(context)
 
-    def coerce_constraint(constraint, the_type=the_type):
-        if the_type is not None:
-            return coerce_value(context, node_filter, the_type, None, None, 
constraint,
+    def coerce_constraint(constraint, value_type=value_type):
+        if value_type is not None:
+            return coerce_value(context, node_filter, value_type, None, None, 
constraint,
                                 constraint_key)
         else:
             return constraint
 
-    def coerce_constraints(constraints, the_type=the_type):
-        if the_type is not None:
-            return tuple(coerce_constraint(constraint, the_type) for 
constraint in constraints)
+    def coerce_constraints(constraints, value_type=value_type):
+        if value_type is not None:
+            return tuple(coerce_constraint(constraint, value_type) for 
constraint in constraints)
         else:
             return constraints
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/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 25e53c6..31865b9 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
@@ -320,9 +320,9 @@ def apply_constraint_to_value(context, presentation, 
constraint_clause, value):
 def get_data_type_value(context, presentation, field_name, type_name):
     value = getattr(presentation, field_name)
     if value is not None:
-        the_type = get_type_by_name(context, type_name, 'data_types')
-        if the_type is not None:
-            return coerce_data_type_value(context, presentation, the_type, 
None, None, value, None)
+        data_type = get_type_by_name(context, type_name, 'data_types')
+        if data_type is not None:
+            return coerce_data_type_value(context, presentation, data_type, 
None, None, value, None)
         else:
             context.validation.report(u'field "{0}" in "{1}" refers to unknown 
data type "{2}"'
                                       .format(field_name, 
presentation._fullname, type_name),

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/tests/extensions/aria_extension_tosca/conftest.py
----------------------------------------------------------------------
diff --git a/tests/extensions/aria_extension_tosca/conftest.py 
b/tests/extensions/aria_extension_tosca/conftest.py
index a2020b7..fdb2d4c 100644
--- a/tests/extensions/aria_extension_tosca/conftest.py
+++ b/tests/extensions/aria_extension_tosca/conftest.py
@@ -17,6 +17,9 @@
 PyTest configuration module.
 
 Add support for a "--tosca-parser" CLI option.
+
+For more information on PyTest hooks, see the `PyTest documentation
+<https://docs.pytest.org/en/latest/writing_plugins.html#pytest-hook-reference>`__.
 """
 
 import pytest

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/tests/mechanisms/parsing/__init__.py
----------------------------------------------------------------------
diff --git a/tests/mechanisms/parsing/__init__.py 
b/tests/mechanisms/parsing/__init__.py
index 2a860dc..a50abc4 100644
--- a/tests/mechanisms/parsing/__init__.py
+++ b/tests/mechanisms/parsing/__init__.py
@@ -27,7 +27,10 @@ class Parsed(object):
         self.verbose = False
 
     def assert_success(self):
-        __tracebackhide__ = True # pylint: disable=unused-variable
+        # See: https://docs.pytest.org/en/latest/example/simple.html
+        #      #writing-well-integrated-assertion-helpers
+        __tracebackhide__ = True                                               
                     # pylint: disable=unused-variable
+
         if len(self.issues) > 0:
             pytest.fail(u'did not expect parsing errors\n\n{0}\n\n{1}'
                         .format(self.text.strip(), u'\n'.join(self.issues)))
@@ -37,7 +40,10 @@ class Parsed(object):
                 print self.text.strip()
 
     def assert_failure(self):
-        __tracebackhide__ = True # pylint: disable=unused-variable
+        # See: https://docs.pytest.org/en/latest/example/simple.html
+        #      #writing-well-integrated-assertion-helpers
+        __tracebackhide__ = True                                               
                     # pylint: disable=unused-variable
+
         if len(self.issues) > 0:
             if self.verbose:
                 print LINE_BREAK

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/1dfb81c8/tests/mechanisms/utils.py
----------------------------------------------------------------------
diff --git a/tests/mechanisms/utils.py b/tests/mechanisms/utils.py
index 3475206..45a442c 100644
--- a/tests/mechanisms/utils.py
+++ b/tests/mechanisms/utils.py
@@ -24,10 +24,13 @@ def matrix(*iterables, **kwargs):
     with the added ability to "flatten" each value by breaking up tuples and 
recombining them into a
     final flat value.
 
-    To do such recombination, use the ``counts`` argument (tuple) to specify 
the number of elements
-    per value in order. Any count greater than 1 (the default) enables 
recombination of that value.
+    To do such recombination, use the ``counts`` argument (tuple of integers) 
to specify the number
+    of elements per value in each iterable in order. Any count greater than 1 
(the default) enables
+    recombination of the iterable's values. So, if you are combining three 
different iterables, then
+    you want ``counts`` to be a tuple of three integers. The first integer in 
the ``counts`` tuple
+    will be the number of elements in the values of the first iterable, etc.
 
-    Example::
+    Detailed example::
 
       x = ('hello', 'goodbye')
       y = ('Linus', 'Richard')
@@ -38,12 +41,18 @@ def matrix(*iterables, **kwargs):
         ('goodbye', 'Richard')
 
       y = (('Linus', 'Torvalds'), ('Richard', 'Stallman'))
+
+      # Without flattening:
+
       matrix(x, y) ->
         ('hello', ('Linus', 'Torvalds')),
         ('hello', ('Richard', 'Stallman')),
         ('goodbye', ('Linus', 'Torvalds')),
         ('goodbye', ('Richard', 'Stallman'))
 
+      # The values in our second iterable, y, have two elements that we want 
to flatten, so we will
+      # set the second "count" value to 2:
+
       matrix(x, y, counts=(1, 2)) ->
         ('hello', 'Linus', 'Torvalds'),
         ('hello', 'Richard', 'Stallman'),

Reply via email to