예제 #1
0
    def handle_soap_call(self, action, arguments_given = None):
        """
Executes the given SOAP action.

:param action: SOAP action called
:param arguments_given: SOAP arguments

:return: (list) Result argument list
:since:  v0.2.00
        """

        # pylint: disable=broad-except,star-args

        if (self.log_handler is not None): self.log_handler.debug("#echo(__FILEPATH__)# -{0!r}.handle_soap_call({1})- (#echo(__LINE__)#)", self, action, context = "pas_upnp")
        _return = UpnpException("pas_http_core_500")

        action_definition = None
        action_method = AbstractService.RE_CAMEL_CASE_SPLITTER.sub("\\1_\\2", action).lower()
        arguments = { }
        if (arguments_given is None): arguments_given = [ ]
        is_request_valid = False

        if (action == "QueryStateVariable"):
            action_definition =  { "argument_variables": [ { "name": "varName", "variable": "A_ARG_TYPE_VarName" } ],
                                   "return_variable": { "name": "return", "variable": "A_ARG_TYPE_VarValue" },
                                   "result_variables": [ ]
                                 }

            variables = { "A_ARG_TYPE_VarName": { "is_sending_events": False,
                                                  "is_multicasting_events": False,
                                                  "type": "string"
                                                },
                          "A_ARG_TYPE_VarValue": { "is_sending_events": False,
                                                   "is_multicasting_events": False,
                                                   "type": "string"
                                                 }
                        }

            if (len(arguments_given) == 1): arguments_given = { "varName": arguments_given.popitem()[1] }
        elif (action in self.actions):
            action_definition = self.actions[action]
            variables = self.variables
        #

        if (action_definition is not None):
            is_request_valid = True

            for argument in action_definition['argument_variables']:
                if (argument['variable'] not in variables):
                    is_request_valid = False
                    _return = UpnpException("pas_http_core_500")

                    break
                elif (argument['name'] in arguments_given): argument_given = arguments_given[argument['name']]
                elif ("value" in variables[argument['variable']]): argument_given = variables[argument['variable']]['value']
                else:
                    is_request_valid = False
                    _return = UpnpException("pas_http_core_400", 402)

                    break
                #

                if (is_request_valid):
                    argument_name = AbstractService.RE_CAMEL_CASE_SPLITTER.sub("\\1_\\2", argument['name']).lower()
                    arguments[argument_name] = Variable.get_native(Variable.get_native_type(variables[argument['variable']]), argument_given)
                #
            #
        else: _return = UpnpException("pas_http_core_400", 401)

        result = None

        try:
            if (is_request_valid):
                result = (getattr(self, action_method)(**arguments)
                          if hasattr(self, action_method) else
                          Hook.call_one("dNG.pas.upnp.services.{0}.handle.{1}".format(self.__class__.__name__, action_method), **arguments)
                         )
            #
        except Exception as handled_exception:
            if (self.log_handler is not None): self.log_handler.error(handled_exception, context = "pas_upnp")
            result = UpnpException("pas_http_core_500", _exception = handled_exception)
        #

        if (isinstance(result, Exception)): _return = result
        elif (is_request_valid):
            return_values = ([ ] if (action_definition['return_variable'] is None) else [ action_definition['return_variable'] ])
            return_values += action_definition['result_variables']
            return_values_length = len(return_values)

            _return = [ ]
            is_dict_result = (type(result) is dict)

            if (return_values_length > 1 and (not is_dict_result)): _return = UpnpException("pas_http_core_500", value = "Response can not be generated based on the UPnP action result from '{0}'".format(self.udn))
            elif (return_values_length > 0):
                for return_value in return_values:
                    return_value_name = AbstractService.RE_CAMEL_CASE_SPLITTER.sub("\\1_\\2", return_value['name']).lower()

                    if (is_dict_result): result_value = (result[return_value_name] if (return_value_name in result) else None)
                    else: result_value = result

                    if (return_value['variable'] not in variables or result_value is None):
                        _return = UpnpException("pas_http_core_500", value = "Variable '{0}' is not defined for '{1}'".format(return_value['variable'], self.udn))
                        break
                    else: _return.append({ "name": return_value['name'], "value": Variable.get_upnp_value(variables[return_value['variable']], result_value) })
                #
            elif (result is not None): _return = UpnpException("pas_http_core_500", value = "Expected empty response does not correspond to UPnP action result from '{0}'".format(self.udn))
        #

        return _return