summaryrefslogtreecommitdiffstats
path: root/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py
diff options
context:
space:
mode:
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py')
-rw-r--r--azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py248
1 files changed, 248 insertions, 0 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py
new file mode 100644
index 0000000..3f9f86d
--- /dev/null
+++ b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/presentation/presentation.py
@@ -0,0 +1,248 @@
+# 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 ...utils.caching import HasCachedMethods
+from ...utils.collections import deepcopy_with_locators
+from ...utils.formatting import safe_repr
+from ...utils.type import full_type_name
+from ...utils.console import puts
+from ..validation import Issue
+from .null import none_to_null
+from .utils import (get_locator, validate_no_short_form, validate_no_unknown_fields,
+ validate_known_fields, validate_primitive)
+
+
+class Value(object):
+ """
+ Encapsulates a typed value assignment.
+ """
+
+ def __init__(self, type_name, value, description, required):
+ self.type = deepcopy_with_locators(type_name)
+ self.value = deepcopy_with_locators(value)
+ self.description = deepcopy_with_locators(description)
+ self.required = deepcopy_with_locators(required)
+
+ def _dump(self, context):
+ if self.type is not None:
+ puts(context.style.type_style(self.type))
+ if self.value is not None:
+ puts(context.style.literal_style(self.value))
+ if self.description is not None:
+ puts(context.style.meta_style(self.description))
+ if self.required is not None:
+ puts(context.style.required_style(self.required))
+
+
+class PresentationBase(HasCachedMethods):
+ """
+ Base class for ARIA presentation classes.
+ """
+
+ def __init__(self, name=None, raw=None, container=None):
+ self._name = name
+ self._raw = raw
+ self._container = container
+ super(PresentationBase, self).__init__()
+
+ @property
+ def as_raw(self):
+ return self._raw
+
+ def _validate(self, context):
+ """
+ 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.
+ """
+
+ @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.
+ """
+
+ if self._name is not None:
+ return self._name
+ elif self._container is not None:
+ return self._container._fullname
+ return full_type_name(self)
+
+ @property
+ def _locator(self):
+ """
+ Attempts to return the most relevant locator, whether we have one, or recursing to our
+ container.
+
+ :rtype: :class:`aria.parser.reading.Locator`
+ """
+
+ return get_locator(self._raw, self._container)
+
+ def _get(self, *names):
+ """
+ Gets attributes recursively.
+ """
+
+ obj = self
+ if (obj is not None) and names:
+ for name in names:
+ obj = getattr(obj, name, None)
+ if obj is None:
+ break
+ return obj
+
+ 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.
+ """
+
+ if names:
+ obj = self._get(*names[:-1])
+ if isinstance(obj, dict):
+ return obj.get(names[-1]) # pylint: disable=no-member
+ return None
+
+ def _get_child_locator(self, *names):
+ """
+ Attempts to return the locator of one our children. Will default to our locator if not
+ found.
+
+ :rtype: :class:`aria.parser.reading.Locator`
+ """
+
+ if hasattr(self._raw, '_locator'):
+ locator = self._raw._locator
+ if locator is not None:
+ return locator.get_child(*names)
+ return self._locator
+
+ def _dump(self, context):
+ """
+ Emits a colorized representation.
+
+ 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:
+ puts(context.style.node(self._name))
+ with context.style.indent():
+ self._dump_content(context)
+ else:
+ self._dump_content(context)
+
+ def _dump_content(self, context, field_names=None):
+ """
+ Emits a colorized representation of the contents.
+
+ The base class will call ``_dump_field`` on all the fields, but subclasses may override
+ this for specialized dumping.
+ """
+
+ if field_names:
+ for field_name in field_names:
+ self._dump_field(context, field_name)
+ elif hasattr(self, '_iter_field_names'):
+ for field_name in self._iter_field_names(): # pylint: disable=no-member
+ self._dump_field(context, field_name)
+ else:
+ puts(context.style.literal_style(self._raw))
+
+ def _dump_field(self, context, field_name):
+ """
+ Emits a colorized representation of the field.
+
+ 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
+ field.dump(self, context)
+
+ def _clone(self, container=None):
+ """
+ Creates a clone of this presentation, optionally allowing for a new container.
+ """
+
+ raw = deepcopy_with_locators(self._raw)
+ if container is None:
+ container = self._container
+ return self.__class__(name=self._name, raw=raw, container=container)
+
+
+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.
+
+ 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.
+ """
+
+ def _validate(self, context):
+ validate_no_short_form(context, self)
+ validate_no_unknown_fields(context, self)
+ validate_known_fields(context, self)
+
+
+class AsIsPresentation(PresentationBase):
+ """
+ Base class for trivial ARIA presentations that provide the raw value as is.
+ """
+
+ def __init__(self, name=None, raw=None, container=None, cls=None):
+ super(AsIsPresentation, self).__init__(name, raw, container)
+ self.cls = cls
+
+ @property
+ def value(self):
+ return none_to_null(self._raw)
+
+ @value.setter
+ def value(self, value):
+ self._raw = value
+
+ @property
+ def _full_cls_name(self):
+ name = full_type_name(self.cls) if self.cls is not None else None
+ if name == 'unicode':
+ # For simplicity, display "unicode" as "str"
+ name = 'str'
+ return name
+
+ def _validate(self, context):
+ try:
+ validate_primitive(self._raw, self.cls, context.validation.allow_primitive_coersion)
+ except ValueError as e:
+ context.validation.report('"%s" is not a valid "%s": %s'
+ % (self._fullname, self._full_cls_name, safe_repr(self._raw)),
+ locator=self._locator,
+ level=Issue.FIELD,
+ exception=e)
+
+ def _dump(self, context):
+ if hasattr(self._raw, '_dump'):
+ puts(context.style.node(self._name))
+ with context.style.indent():
+ self._raw._dump(context)
+ else:
+ super(AsIsPresentation, self)._dump(context)