"""This class contains methods related to service management. It contains all type of services proposed in theFunctional View of RAMI 4.0."""importinspectimportjsonimportlogging_logger=logging.getLogger(__name__)
[docs]classAgentServiceUtils:""" This class contains utility methods related to the Agent Services. """
[docs]@staticmethodasyncdefget_agent_service_parameters(service_method):""" This method gets the required information about the parameters of the agent service: the names and types of service method parameters. Args: service_method (method): method of the agent service. Returns: dict: dictionary with all information about the parameters of the agent service. """ifservice_methodisNone:raiseKeyError(f"The service method {service_method} does not exist in this DT.")else:# Obtain the signature of the methodsig=inspect.signature(service_method)params=sig.parameters# Construct the dictionary with the information of the parametersparams_details={nombre:{'annotation':parametro.annotation,'type':parametro.annotationifparametro.annotationisnotinspect.Parameter.emptyelsestr,}fornombre,parametroinparams.items()}returnparams_details
[docs]@staticmethodasyncdefget_adapted_service_parameters(service_method,**kwargs):""" This method adapts the received parameters values to the required types of the service method, in order to be correctly executed. Args: service_method (method): method of the agent service. **kwargs: received parameters with the values. Returns: dict: parameters correctly adapted to the method. """ifservice_methodisNone:ValueError(f"A null object has been offered for the {service_method} method, its parameters cannot be "f"obtained.")# The information of the required method parameters is obtainedrequired_params_info=awaitAgentServiceUtils.get_agent_service_parameters(service_method)adapted_params={}# The received parameters with the values are available in kwargsiflen(required_params_info)!=0and((kwargsisNone)or(len(kwargs)==0)):raiseValueError(f"The service method cannot be executed because the required parameters have not been "f"provided.")forparam_name,valueinkwargs.items():ifparam_nameinrequired_params_info:tipo=required_params_info[param_name]['type']try:iftipo==bool:# bool(value) is true as long as the string is not empty, son it cannot be used.adapted_params[param_name]=value.lower()in('yes','true','t','1')eliftipo==list[dict]:# In this case it is a complex type, so it will use json libraryifnotisinstance(value,list):adapted_params[param_name]=json.loads(value)else:adapted_params[param_name]=valueelse:adapted_params[param_name]=tipo(value)exceptValueErrorase:raiseValueError(f"Could not transform the value {value} for the parameter '{param_name}',"f" reason: {e}")else:raiseValueError(f"Parameter {param_name} not found in method {service_method}.")returnadapted_params
[docs]@staticmethodasyncdefadapt_received_service_parameters(service_method,received_service_params):""" This method adapts the received parameters values to the required of the service execution method. Args: service_method (method): method of the agent service. received_service_params: received service parameters Returns: obj: adapted service parameters """required_svc_params=awaitAgentServiceUtils.get_agent_service_parameters(service_method)iflen(required_svc_params)==0:return{}iflen(required_svc_params)>1:# If there are more than one service parameter, it is adapted with the specific methodreturnawaitAgentServiceUtils.get_adapted_service_parameters(service_method,**received_service_params)else:# If there is only one parameter, the data will be received without the parameter name, so it is obtained# and addedreturn{next(iter(required_svc_params)):received_service_params}
[docs]@staticmethodasyncdefsafe_execute_agent_service(service_method,**kwargs):""" This method executes the agent service securely, regardless of the execution method, synchronous or asynchronous. Args: service_method: executable method of the agent service. **kwargs: in case the execution method has parameters, they are passed as kwargs. Returns: result of the execution of the agent service. """ifisinstance(service_method,staticmethod):method_function=service_method.__func__else:method_function=service_methodifinspect.iscoroutinefunction(method_function):returnawaitservice_method(**kwargs)else:returnservice_method(**kwargs)