Beispiel #1
0
    def visit_struct(self, typ):
        """
        Visit StructValue

        :type  typ: :class:`vmware.vapi.bindings.type.StructType`
        :param typ: Binding type of the value
        """
        in_value = self._in_value
        out_value = {}
        typ_field_names = typ.get_field_names()
        value_field_names = in_value.get_field_names()

        for field_name in typ_field_names:
            if typ.binding_class:
                pep_name = typ.binding_class._get_pep_name(field_name)  # pylint: disable=W0212
            else:
                pep_name = Converter.canonical_to_pep(field_name)
            field_type = typ.get_field(field_name)
            # When the request is converted from DataValue to Native value
            # on the server side:
            # - if the client - server version matches: we wont hit this case
            # - if new client talks to old server, runtime would have
            #   raised InvalidArgument error if there are unexpected optional
            #   fields
            # - if old client talks to new server, runtime adds the missing
            #   optional fields, so we wont hit this case
            #
            # When the response is converted from DataValue to Native value
            # on the client side:
            # - if the client - server version matches: we wont hit this case
            # - if new client talks to old server,  client bindings should
            #   tolerate the absence of expected optional properties. So,
            #   we have to set it to None!
            # - if old client talks to new server, we will visit all the known
            #   fields here and the unexpected fields are added to the
            #   VapiStruct object
            if ((isinstance(field_type, OptionalType)
                 or self._allow_skip_struct_fields)
                    and not in_value.has_field(field_name)):
                out_value[pep_name] = None
            else:
                out_value[pep_name] = self._visit_struct_field(
                    in_value.get_field(field_name), field_type)
        self._in_value = in_value

        struct_class = typ.binding_class
        if struct_class is not None:
            struct_class.validate_struct_value(self._in_value)
            self._out_value = struct_class(**out_value)

            # Fields present in struct value but not in struct binding type.
            extra_field_names = set(value_field_names) - set(typ_field_names)
            if extra_field_names:
                extra_fields = {}
                for field_name in extra_field_names:
                    extra_fields[field_name] = in_value.get_field(field_name)
                self._out_value._set_extra_fields(extra_fields)  # pylint: disable=E1103,W0212
        else:
            self._out_value = out_value
Beispiel #2
0
    def _get_pep_name(cls, canonical_name):
        """
        Return the pep name for the provided canonical name

        :rtype: :class:`str`
        :return: Pep name used in the binding
        """
        if (cls._canonical_to_pep_names
                and canonical_name in cls._canonical_to_pep_names):
            return cls._canonical_to_pep_names[canonical_name]
        else:
            return Converter.canonical_to_pep(canonical_name)
Beispiel #3
0
 def __dir__(cls):
     """
     Return the names of the factory methods that are synthesized for each of
     standard error types in addition to the name of the attributes in the
     base class (object).
     """
     #pylint: disable=R0201
     method_names = [
         'new_' + Converter.capwords_to_underscore(name)
         for name in enumerate_standard_error_names()
     ]
     return sorted(dir(object) + method_names)
Beispiel #4
0
def _pepify_args(meth_args):
    """
    Pepify the names of the method arguments

    :type  meth_args: :class:`dict`
    :param meth_args: Actual method arguments
    :rtype: :class:`dict`
    :return: Modified method arguments with pepified names
    """
    new_args = {}
    for k, v in six.iteritems(meth_args):
        new_args[Converter.pepify(k)] = v
    return new_args
Beispiel #5
0
    def _pepify_args(meth_args):
        """
        Converts all the keys of given keyword arguments into PEP8 standard
        names

        :type  meth_args: :class:`dict`
        :param meth_args: The keyword arguments to be converted
        :rtype:  :class:`dict`
        :return: The converted keyword arguments
        """
        new_args = {}
        for k, v in six.iteritems(meth_args):
            new_args[Converter.canonical_to_pep(k)] = v
        return new_args
Beispiel #6
0
def _build_py_value(data_value, data_def, impl=None):
    """"
    Converts a data value to python native value
    impl input is required to create Struct class instances

    :type  data_value: :class:`vmware.vapi.data.value.DataValue`
    :param data_value: Input data value
    :type  data_def: :class:`vmware.vapi.data.definition.DataDefinition`
    :param data_def: Data definition
    :type  impl: :class:`vmware.vapi.bindings.stub.VapiInterface` or
        :class:`vmware.vapi.bindings.skeleton.VapiInterface` or ``None``
    :param impl: Python generated class to resolve structure classes
    :rtype: :class:`object`
    :return: Native python value
    """
    if data_def.type == Type.OPTIONAL:
        if data_value.is_set():
            element_def = data_def.element_type
            element_value = data_value.value
            py_value = _build_py_value(element_value, element_def, impl)
        else:
            py_value = None
    elif data_def.type == Type.LIST:
        py_value = []
        element_def = data_def.element_type
        for element_value in data_value:
            py_value.append(_build_py_value(element_value, element_def, impl))
    elif data_def.type in (Type.STRUCTURE, Type.ERROR):
        struct_name = data_def.name
        class_name = Converter.underscore_to_capwords(struct_name)
        py_value = {}
        for field in data_def.get_field_names():
            field_def = data_def.get_field(field)
            field_val = data_value.get_field(field)
            py_value[field] = _build_py_value(field_val, field_def, impl)
        if impl and hasattr(impl, class_name):
            kwargs = _pepify_args(py_value)
            py_value = getattr(impl, class_name)(**kwargs)
    elif data_def.type == Type.VOID:
        py_value = None
    # For opaque value, no need of any conversion
    elif data_def.type == Type.OPAQUE:
        py_value = data_value
    # Primitive type Integer/Double/String/Boolean/Secret
    else:
        py_type = _py_type_map.get(data_def.type)
        py_value = py_type(data_value.value)
    return py_value
Beispiel #7
0
    def create_stub(self, service_name):
        """
        Create a stub corresponding to the specified service name

        :type  service_name: :class:`str`
        :param service_name: Name of the service

        :rtype: :class:`VapiInterface`
        :return: The stub correspoding to the specified service name
        """
        path_split = service_name.split('.')
        module_name = '%s_client' % '.'.join(path_split[:-1])
        class_name = Converter.underscore_to_capwords(path_split[-1])
        module = __import__(module_name, globals(), locals(), class_name)
        cls = getattr(module, class_name)
        return cls(self._config)
Beispiel #8
0
    def visit(self, value):
        """
        Dispatch the call to the appropriate method based
        on the type of the input argument

        :type  value: :class:`object`
        :param value: The object to be used for dispatch
        """
        class_name = value.__class__.__name__
        method = self._cache.get(class_name)
        if not method:
            type_name = class_name
            if self._suffix and type_name.endswith(self._suffix):
                type_name = type_name[:-len(self._suffix)]
            type_name = Converter.capwords_to_underscore(type_name)
            method = getattr(self, 'visit_' + type_name)
            self._cache[class_name] = method
        return method(value)
Beispiel #9
0
    def __getattr__(cls, name):
        """
        Return a synthesized factory method if the given name matches the
        name of one of the standard error types (after converting from
        lower-case-with-underscores to cap-words).
        """
        if name.startswith(cls.METHOD_PREFIX) and name is not 'new_vapi_error':
            canonical_error_type_name = name[cls.METHOD_PREFIX_LENGTH:]
            capwords_error_type_name = Converter.underscore_to_capwords(
                canonical_error_type_name)
            error_type = getattr(errors_provider, capwords_error_type_name)
            if (isinstance(error_type, type)
                    and issubclass(error_type, VapiError)):

                def factory_method(**kwargs):
                    """
                    Synthesized factory function for a standard error type.
                    """
                    return error_type(**kwargs)

                return factory_method
        msg = "type object '%s' has no attribute '%s'" % (cls.__name__, name)
        raise AttributeError(msg)
Beispiel #10
0
    def _visit_python_dict(self, typ):
        """
        Visit an instance of Python native dictionary

        :type  typ: :class:`vmware.vapi.bindings.type.StructType`
        :param typ: Binding type of the value
        :rtype: :class:`vmware.vapi.data.value.DataValue`
        :return: vAPI Data value
        """
        in_value = self._in_value
        out_value = typ.definition.new_value()
        field_names = typ.get_field_names()
        for field_name in field_names:
            field_type = typ.get_field(field_name)
            try:
                if typ.binding_class:
                    # pylint: disable=W0212
                    pep_name = typ.binding_class._get_pep_name(field_name)
                else:
                    pep_name = Converter.canonical_to_pep(field_name)
                self._in_value = in_value[pep_name]
            except KeyError:
                if isinstance(field_type, OptionalType):
                    # If the field is optional, then tolerate
                    # the absence of it in the dictionary
                    self._in_value = None
                else:
                    msg = message_factory.get_message(
                        'vapi.bindings.typeconverter.dict.missing.key',
                        pep_name)
                    logger.debug(msg)
                    raise CoreException(msg)
            self.visit(field_type)
            out_value.set_field(field_name, self._out_value)
        self._in_value = in_value
        self._out_value = out_value
 def test_capitalize(self):
     self.assertEqual(Converter.capitalize('abc'), 'Abc')
Beispiel #12
0
    def invoke(self, ctx, method_id, input_value):
        """
        Invokes the specified method using the execution context and
        the input provided

        :type  ctx: :class:`vmware.vapi.core.ExecutionContext`
        :param ctx: Execution context for this method
        :type  input_value: :class:`vmware.vapi.data.value.StructValue`
        :param input_value: Method input parameters

        :rtype: :class:`vmware.vapi.core.MethodResult`
        :return: Result of the method invocation
        """
        op_info = self._operations.get(method_id.get_name())

        # Set execution context
        set_context(ctx)

        try:
            # input validators
            validators = op_info['input_value_validator_list']
            input_type = op_info['input_type']
            for validator in validators:
                msg_list = validator.validate(input_value, input_type)
                if msg_list:
                    error_value = make_error_value_from_msgs(
                        self._invalid_argument_def, *msg_list)
                    return MethodResult(error=error_value)
            error_value = ApiInterfaceSkeleton.check_for_unknown_fields(
                input_type, input_value)
            if error_value:
                return MethodResult(error=error_value)

            try:
                meth_args = TypeConverter.convert_to_python(
                    input_value, binding_type=input_type,
                    resolver=self._resolver)
            except CoreException as e:
                error_value = make_error_value_from_msgs(
                    self._invalid_argument_def, *e.messages)
                return MethodResult(error=error_value)

            method_name = Converter.canonical_to_pep(
                            get_non_task_operation_name(method_id.get_name()))
            method = getattr(self._impl, method_name)

            # If it's a task method then create a new thread to run provider
            # impl and return task id or result depending upon type of
            # invocation.
            if op_info['task_type'] != TaskType.NONE:
                meth_output, task_accepted = self._invoke_task_operation(
                    ctx, method_id, method, meth_args)

                if isinstance(meth_output, VapiError):
                    raise meth_output  # pylint: disable=raising-bad-type

                # In case of provider not accepting task throw an error.
                if task_accepted is False:
                    msg_list = [message_factory.get_message(
                                'vapi.bindings.skeleton.task.invalidstate')]
                    error_value = make_error_value_from_msgs(
                        self._internal_server_error_def,
                        *msg_list)
                    return MethodResult(error=error_value)
            else:
                meth_output = method(**meth_args)

            output_type = op_info['output_type']
            # output validators
            validators = op_info['output_validator_list']

            output = TypeConverter.convert_to_vapi(meth_output,
                                                   output_type)

            for validator in validators:
                msg_list = validator.validate(output, output_type)
                if msg_list:
                    error_value = make_error_value_from_msgs(
                        self._internal_server_error_def, *msg_list)
                    return MethodResult(error=error_value)
            result = MethodResult(output=output)
        except CoreException as e:
            logger.exception("Error in invoking %s - %s",
                             str(method_id), e)
            error_value = make_error_value_from_msgs(
                self._internal_server_error_def,
                *e.messages)
            result = MethodResult(error=error_value)
        except VapiError as e:
            exc_info = sys.exc_info()
            error_type = e.__class__.get_binding_type()
            try:
                error = TypeConverter.convert_to_vapi(e, error_type)
            except CoreException as ce:
                logger.error('Failed to convert %s to error type %s because %s',
                             e, error_type.name,
                             ' because '.join((e.def_msg for e in ce.messages)),
                             exc_info=exc_info)
                raise
            result = MethodResult(error=error)
        finally:
            # Reset the execution context after the operation
            clear_context()

        return result
 def test_capwords_to_underscore(self):
     self.assertEqual(Converter.mixedcase_to_underscore('CapWords'),
                      'cap_words')
     self.assertEqual(Converter.mixedcase_to_underscore('cap_words'),
                      'cap_words')
 def test_underscore_to_mixedcase(self):
     self.assertEqual(Converter.underscore_to_mixedcase('mixed_case'),
                      'mixedCase')
     self.assertEqual(Converter.underscore_to_mixedcase('mixedCase'),
                      'mixedCase')
 def test_uncapitalize(self):
     self.assertEqual(Converter.uncapitalize('Abc'), 'abc')
 def test_underscore_to_capwords(self):
     self.assertEqual(Converter.underscore_to_capwords('cap_words'),
                      'CapWords')
     self.assertEqual(Converter.underscore_to_capwords('CapWords'),
                      'CapWords')
 def test_pepify(self):
     self.assertEqual(Converter.pepify('class'), 'class_')