Source code for vmware.vapi.data.value

"""
vAPI DataValues
"""

__author__ = 'VMware, Inc.'
__copyright__ = 'Copyright 2011-2014 VMware, Inc.  All rights reserved. -- VMware Confidential'

import logging
import math
import six
from decimal import Decimal

from vmware.vapi.exception import CoreException
from vmware.vapi.data.type import Type
from vmware.vapi.lib.visitor import VapiVisitor
from vmware.vapi.l10n.runtime import message_factory

logger = logging.getLogger(__name__)


[docs]class DataValue(object): """ A piece of introspectable value in vAPI infrastructure :type type: :class:`vmware.vapi.data.type.Type` :ivar type: Type of DataValue """ def __init__(self, data_type=None): """ Initialize DataValue :type data_type: :class:`vmware.vapi.data.type.Type` :param data_type: Type of DataValue """ self.type = data_type
[docs] def accept(self, visitor): """ Applies a visitor to this DataValue :type visitor: :class:`SimpleValueVisitor` :param visitor: visitor operating on this DataValue """ visitor.visit(self)
[docs]class PrimitiveDataValue(DataValue): """ Base class for all primitive DataValues :type value: :class:`object` :ivar value: Primitive value """ def __init__(self, *args, **kwargs): DataValue.__init__(self, *args, **kwargs) self.value = None def __repr__(self): return '%s(value=%s)' % (self.__class__.__name__, repr(self.value))
[docs]class ComparableValueMixin(object): """ Helper class to implement the rich comparator operations. """ def __eq__(self, other): if isinstance(other, self.__class__): return self.value == other.value else: return NotImplemented def __ne__(self, other): if isinstance(other, self.__class__): return self.value != other.value else: return NotImplemented def __lt__(self, other): if isinstance(other, self.__class__): return self.value < other.value else: return NotImplemented def __gt__(self, other): if isinstance(other, self.__class__): return self.value > other.value else: return NotImplemented def __le__(self, other): if isinstance(other, self.__class__): return self.value <= other.value else: return NotImplemented def __ge__(self, other): if isinstance(other, self.__class__): return self.value >= other.value else: return NotImplemented def __hash__(self): return hash(self.value)
[docs]class IntegerValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for integer values :type value: :class:`int` :ivar value: 64 bit signed int present in IntegerValue """ def __init__(self, value=0): """ Initialize IntegerValue :type value: :class:`int` :kwarg value: Integer value to be initialized """ PrimitiveDataValue.__init__(self, Type.INTEGER) ComparableValueMixin.__init__(self) if not isinstance(value, six.integer_types): msg = message_factory.get_message("vapi.data.invalid", self.type, type(value).__name__) logger.debug(msg) raise CoreException(msg) self.value = value
[docs]class DoubleValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for float values :type value: :class:`float` or :class:`decimal.Decimal` :ivar value: 64 bit signed float present in DoubleValue """ def __init__(self, value=0.0): """ Initialize DoubleValue :type value: :class:`float` or :class:`decimal.Decimal` :kwarg value: Float or decimal.Decimal value to be initialized """ PrimitiveDataValue.__init__(self, Type.DOUBLE) ComparableValueMixin.__init__(self) if not isinstance(value, float) and not isinstance(value, Decimal): msg = message_factory.get_message('vapi.data.invalid', self.type, type(value).__name__) logger.debug(msg) raise CoreException(msg) # Accept floats, but store as decimal if isinstance(value, float): value = Decimal(str(value)) if isinstance(value, Decimal): if math.isinf(float(value)): msg = message_factory.get_message('vapi.data.invalid.double.inf', value) logger.debug(msg) raise CoreException(msg) self.value = value
[docs]class StringValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for strings :type value: :class:`str` :ivar value: String present in StringValue """ def __init__(self, value=""): """ Initialize StringValue :type value: :class:`str` :kwarg value: String value to be initialized """ PrimitiveDataValue.__init__(self, Type.STRING) ComparableValueMixin.__init__(self) if not isinstance(value, six.string_types): msg = message_factory.get_message("vapi.data.invalid", self.type, type(value).__name__) logger.debug(msg) raise CoreException(msg) self.value = value
[docs]class BooleanValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for bool values :type value: :class:`bool` :ivar value: Bool present in BooleanValue """ def __init__(self, value=False): """ Initialize BooleanValue :type value: :class:`bool` :kwarg value: Bool value to be initialized """ PrimitiveDataValue.__init__(self, Type.BOOLEAN) ComparableValueMixin.__init__(self) if not isinstance(value, bool): msg = message_factory.get_message("vapi.data.invalid", self.type, type(value).__name__) logger.debug(msg) raise CoreException(msg) self.value = value
[docs]class BlobValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for binary values :type value: :class:`bytes` :ivar value: Binary present in BlobValue """ def __init__(self, value=""): """ Initialize BooleanValue :type value: :class:`bytes` :kwarg value: Binary value to be initialized """ PrimitiveDataValue.__init__(self, Type.BLOB) ComparableValueMixin.__init__(self) self.value = value
[docs]class VoidValue(PrimitiveDataValue): """ DataValue class for None """ def __init__(self): """ Initialize VoidValue """ PrimitiveDataValue.__init__(self, Type.VOID) def __eq__(self, other): if isinstance(other, VoidValue): return True else: return False def __ne__(self, other): return not (self == other) def __hash__(self): return hash(None) def __repr__(self): return 'VoidValue()' # Disabling the pylint complaint about badly implemented container # as we don't need __setitem__, __delitem__ and __getitem__
[docs]class ListValue(DataValue): # pylint: disable=R0924 """ DataValue class for lists """ def __init__(self, values=None): """ Initialize ListValue """ DataValue.__init__(self, Type.LIST) if values is not None and not isinstance(values, list): msg = message_factory.get_message("vapi.data.invalid", self.type, type(values).__name__) logger.debug(msg) raise CoreException(msg) self._list_val = values if values is not None else []
[docs] def add(self, value): """ Add an element to ListValue :type value: :class:`DataValue` :param value: DataValue to be added """ self._list_val.append(value)
[docs] def add_all(self, values): """ Add all the elements from input list to ListValue :type values: :class:`list` of :class:`DataValue` :param values: List of DataValues to be added """ for value in values: self.add(value)
[docs] def is_empty(self): """ Returns true if the list is empty :rtype: :class:`bool` :return: True if the list is empty, false otherwise """ return not self._list_val
[docs] def size(self): """ Returns the size of the list :rtype: :class:`int` :return: Size of the list value """ return len(self._list_val)
def __eq__(self, other): if not isinstance(other, ListValue): return False if self.size() != other.size(): return False for self_item, other_item in zip(self, other): if self_item != other_item: return False return True def __ne__(self, other): return not (self == other) def __iter__(self): return self._list_val.__iter__() def __len__(self): return len(self._list_val) def __repr__(self): ret = ', '.join([repr(val) for val in self._list_val]) return 'ListValue(values=[%s])' % ret
[docs]class OptionalValue(DataValue, ComparableValueMixin): """ DataValue class for optionals :type value: :class:`DataValue` :ivar value: DataValue present in this OptionalValue """ def __init__(self, value=None): """ Initialize OptionalValue :type value: :class:`DataValue` :kwarg value: DataValue to be used in OptionalValue """ DataValue.__init__(self, Type.OPTIONAL) ComparableValueMixin.__init__(self) self.value = value
[docs] def is_set(self): """ Returns true if OptionalValue has a DataValue present in it :rtype: :class:`bool` :return: Returns true if OptionalValue is initialized with some DataValue, false otherwise """ return self.value is not None
def __repr__(self): return 'OptionalValue(%s)' % repr(self.value)
[docs]class StructValue(DataValue): """ DataValue class for Structures :type name: :class:`str` :ivar name: Name of the structure """ def __init__(self, name=None, data_type=Type.STRUCTURE, values=None): """ Initialize StructValue :type name: :class:`str` :kwarg name: Name of the StructValue """ DataValue.__init__(self, data_type) self.name = name if values is not None and not isinstance(values, dict): msg = message_factory.get_message("vapi.data.invalid", self.type, type(values).__name__) logger.debug(msg) raise CoreException(msg) self._fields = values if values is not None else {}
[docs] def get_fields(self): """ Returns the map of field names and values present in this StructValue. :rtype: :class:`dict` of :class:`str` and :class:`DataValue` :return: Fields in this struct value """ return six.iteritems(self._fields)
[docs] def get_field_names(self): """ Returns the list of field names present in this StructValue. The ordering of fields is not preserved. :rtype: :class:`list` of :class:`str` :return: List of field names present in this StructValue """ return list(self._fields.keys())
[docs] def has_field(self, field): """ Returns true if the field is present in the StructValue, false otherwise :type field: :class:`str` :param field: Name of the field :rtype: :class:`bool` :return: Returns true if the field is present in the StructValue, false otherwise """ return field in self._fields
[docs] def get_field(self, field): """ Returns the field value of the field present in the StructValue :type field: :class:`str` :param field: Name of the field :rtype: :class:`DataValue` :return: Returns the field value of the field present in the StructValue """ value = self._fields.get(field) if value is None: msg = message_factory.get_message( "vapi.data.structure.getfield.unknown", field) logger.debug(msg) raise CoreException(msg) return value
[docs] def set_field(self, field, value): """ Set the field value for the field name passed in the argument :type field: :class:`str` :param field: Name of the field :type field: :class:`str` :param field: Name of the field to be set :type value: :class:`DataValue` :param value: DataValue to be used for the field """ if value is None: msg = message_factory.get_message( "vapi.data.structure.setfield.null", field) logger.debug(msg) raise CoreException(msg) self._fields[field] = value
def __eq__(self, other): if not isinstance(other, StructValue): return False if self.name != other.name: return False if sorted(self.get_field_names()) != sorted(other.get_field_names()): return False for key, value in six.iteritems(self._fields): if value != other.get_field(key): return False return True def __ne__(self, other): return not (self == other) def __repr__(self): return "StructValue(name=%s, values=%s)" % (repr(self.name), repr(self._fields))
[docs] def keys(self): """ Returns the list of field names :rtype: :class:`list` or :class:`str` :return: List of field names """ return six.iterkeys(self._fields)
[docs]class ErrorValue(StructValue): """ DataValue class for Errors """ def __init__(self, name=None, values=None): """ Initialize ErrorValue :type name: :class:`str` :kwarg name: Name of the ErrorValue """ StructValue.__init__(self, name, Type.ERROR, values) def __eq__(self, other): if not isinstance(other, ErrorValue): return False return StructValue.__eq__(self, other) def __ne__(self, other): return not (self == other)
[docs]class SecretValue(PrimitiveDataValue, ComparableValueMixin): """ DataValue class for secret values. Only strings are allowed to be secrets. :type value: :class:`str` :ivar value: String present in SecretValue """ def __init__(self, value=""): """ Initialize StringValue :type value: :class:`str` :kwarg value: String value to be initialized """ PrimitiveDataValue.__init__(self, Type.SECRET) ComparableValueMixin.__init__(self) if not isinstance(value, six.string_types): msg = message_factory.get_message("vapi.data.invalid", self.type, type(value).__name__) raise CoreException(msg) self.value = value def __repr__(self): return 'SecretValue(<secret>)' def __str__(self): return '<secret>'
[docs]class SimpleValueVisitor(VapiVisitor): """ Base no-op implementation of a DataValue visitor """ def __init__(self): """ Initialize SimpleValueVisitor """ VapiVisitor.__init__(self, 'Value')
[docs] def visit_void(self, value): """ Visit a VoidValue :type value: :class:`VoidValue` :param value: Data value """ pass
[docs] def visit_integer(self, value): """ Visit a IntegerValue :type value: :class:`IntegerValue` :param value: Data value """ pass
[docs] def visit_double(self, value): """ Visit a DoubleValue :type value: :class:`DoubleValue` :param value: Data value """ pass
[docs] def visit_string(self, value): """ Visit a StringValue :type value: :class:`StringValue` :param value: Data value """ pass
[docs] def visit_boolean(self, value): """ Visit a BooleanValue :type value: :class:`BooleanValue` :param value: Data value """ pass
[docs] def visit_blob(self, value): """ Visit a BlobValue :type value: :class:`BlobValue` :param value: Data value """ pass
[docs] def visit_list(self, value): """ Visit a ListValue :type value: :class:`ListValue` :param value: Data value """ pass
[docs] def visit_optional(self, value): """ Visit a OptionalValue :type value: :class:`OptionalValue` :param value: Data value """ pass
[docs] def visit_struct(self, value): """ Visit a StructValue :type value: :class:`StructValue` :param value: Data value """ pass
[docs] def visit_error(self, value): """ Visit an ErrorValue :type value: :class:`ErrorValue` :param value: Data value """ pass
[docs] def visit_secret(self, value): """ Visit a SecretValue :type value: :class:`SecretValue` :param value: Data value """ pass # vapi type name to vapi type value map
type_map = { Type.VOID: VoidValue, Type.INTEGER: IntegerValue, Type.DOUBLE: DoubleValue, Type.STRING: StringValue, Type.BOOLEAN: BooleanValue, Type.LIST: ListValue, Type.STRUCTURE: StructValue, Type.ERROR: ErrorValue, Type.OPTIONAL: OptionalValue, Type.BLOB: BlobValue, Type.SECRET: SecretValue, }
[docs]def data_value_factory(data_type, *args): """ Convenience method to create datavalues :type data_type: :class:`str` :param data_type: String representation of the data value type :param args: The argument list to be passed to the data value constructor """ constructor = type_map.get(data_type) return constructor(*args)