diff options
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py')
-rw-r--r-- | azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py new file mode 100644 index 0000000..f0fd390 --- /dev/null +++ b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/utils.py @@ -0,0 +1,187 @@ +# 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 types import FunctionType + +from ...utils.formatting import safe_repr +from ...utils.type import full_type_name +from ..validation import Issue +from .null import NULL + + +def get_locator(*values): + """ + Gets the first available locator. + + :rtype: :class:`aria.parser.reading.Locator` + """ + + for v in values: + if hasattr(v, '_locator'): + locator = v._locator + if locator is not None: + return locator + return None + + +def parse_types_dict_names(types_dict_names): + """ + If the first element in the array is a function, extracts it out. + """ + + convert = None + if isinstance(types_dict_names[0], FunctionType): + convert = types_dict_names[0] + types_dict_names = types_dict_names[1:] + return types_dict_names, convert + + +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 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): + if (cls is unicode) or (cls is str): # These two types are interchangeable + valid = isinstance(value, basestring) + elif cls is int: + # In Python, a bool is an int + valid = isinstance(value, int) and not isinstance(value, bool) + else: + valid = isinstance(value, cls) + if not valid: + if coerce: + value = cls(value) + else: + raise ValueError('not a "%s": %s' % (full_type_name(cls), safe_repr(value))) + return value + + +def validate_no_short_form(context, presentation): + """ + Makes sure that we can use short form definitions only if we allowed it. + """ + + if not hasattr(presentation, 'SHORT_FORM_FIELD') and not isinstance(presentation._raw, dict): + context.validation.report('short form not allowed for field "%s"' % presentation._fullname, + locator=presentation._locator, + level=Issue.BETWEEN_FIELDS) + + +def validate_no_unknown_fields(context, presentation): + """ + Make sure that we can use unknown fields only if we allowed it. + """ + + if not getattr(presentation, 'ALLOW_UNKNOWN_FIELDS', False) \ + and not context.validation.allow_unknown_fields \ + and isinstance(presentation._raw, dict) \ + and hasattr(presentation, 'FIELDS'): + for k in presentation._raw: + if k not in presentation.FIELDS: + context.validation.report('field "%s" is not supported in "%s"' + % (k, presentation._fullname), + locator=presentation._get_child_locator(k), + level=Issue.BETWEEN_FIELDS) + + +def validate_known_fields(context, presentation): + """ + Validates all known fields. + """ + + if hasattr(presentation, '_iter_fields'): + for _, field in presentation._iter_fields(): + field.validate(presentation, context) + + +def get_parent_presentation(context, presentation, *types_dict_names): + """ + 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 + ``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 + + if type_name is None: + return None + + types_dict_names, convert = parse_types_dict_names(types_dict_names) + types_dict = context.presentation.get('service_template', *types_dict_names) or {} + + if convert: + type_name = convert(context, type_name, types_dict) + + # Make sure not derived from self + if type_name == presentation._name: + return None + # Make sure derived from type exists + elif type_name not in types_dict: + return None + else: + # Make sure derivation hierarchy is not circular + hierarchy = [presentation._name] + presentation_copy = presentation + while presentation_copy.derived_from is not None: + derived_from = presentation_copy.derived_from + if convert: + derived_from = convert(context, derived_from, types_dict) + + if derived_from == presentation_copy._name or derived_from not in types_dict: + return None + presentation_copy = types_dict[derived_from] + if presentation_copy._name in hierarchy: + return None + hierarchy.append(presentation_copy._name) + + return types_dict[type_name] + + +def report_issue_for_unknown_type(context, presentation, type_name, field_name, value=None): + if value is None: + value = getattr(presentation, field_name) + context.validation.report('"%s" refers to an unknown %s in "%s": %s' + % (field_name, type_name, presentation._fullname, safe_repr(value)), + locator=presentation._get_child_locator(field_name), + level=Issue.BETWEEN_TYPES) + + +def report_issue_for_parent_is_self(context, presentation, field_name): + context.validation.report('parent type of "%s" is self' % presentation._fullname, + locator=presentation._get_child_locator(field_name), + level=Issue.BETWEEN_TYPES) + + +def report_issue_for_unknown_parent_type(context, presentation, field_name): + context.validation.report('unknown parent type "%s" in "%s"' + % (getattr(presentation, field_name), presentation._fullname), + locator=presentation._get_child_locator(field_name), + level=Issue.BETWEEN_TYPES) + + +def report_issue_for_circular_type_hierarchy(context, presentation, field_name): + context.validation.report('"%s" of "%s" creates a circular type hierarchy' + % (getattr(presentation, field_name), presentation._fullname), + locator=presentation._get_child_locator(field_name), + level=Issue.BETWEEN_TYPES) |