def test_seq4_delete(self): step = "------ step 1: create tan ------" self.info(step) count_implem_init = ImplementationDao.objects.count() count_profile_item_init = ProfileItemDao.objects.count() self.info("Before created: ImplementationDao count = %s" % count_implem_init) self.info("Before created: ProfileItemDao count = %s" % count_profile_item_init) created_tan = ImplementationDao.create( TestImplementationDaoCRUD.my_tan) self.info(" - Original tan oper: %s" % str(TestImplementationDaoCRUD.my_tan)) self.info(" - Created tan oper: %s" % str(created_tan)) step = "------ step 2: simple case of delete ------" self.info(step) ImplementationDao.delete_resource(created_tan) count_implem_post = ImplementationDao.objects.count() count_profile_item_post = ProfileItemDao.objects.count() self.info("Once deleted: ImplementationDao count = %s" % count_implem_post) self.info("Once deleted: ProfileItemDao count = %s" % count_profile_item_post) self.assertEqual(count_implem_init, count_implem_post) self.assertEqual(count_profile_item_init, count_profile_item_post)
def test_seq2_find(self): self.info("TestImplementationDaoCRUD::test_seq2_find") created_cosinus = ImplementationDao.create( TestImplementationDaoCRUD.my_cosinus) TestImplementationDaoCRUD.my_created_cosinus = created_cosinus self.info( "After test_seq2_find: step 1 CREATE cos: ImplementationDao count = %s" % ImplementationDao.objects.count()) self.info("Original %s" % str(TestImplementationDaoCRUD.my_cosinus)) self.info("Created %s" % str(created_cosinus)) self.info("test_seq2_find_from_key [%s]: step 2 FIND by id: " % TestImplementationDaoCRUD.my_created_cosinus.db_id) self.info( "Before test_seq2_find_from_key: ImplementationDao count = %s" % ImplementationDao.objects.count()) res = ImplementationDao.find_from_key( TestImplementationDaoCRUD.my_created_cosinus.db_id) self.assertIsNotNone( res, "Failed find_by_key [%s]" % TestImplementationDaoCRUD.my_created_cosinus.db_id) self.info("Found %s" % str(res)) self.info("test_seq2_find: step 3 FIND by values: [%s][%s][%s]" % (TestImplementationDaoCRUD.my_cosinus.name, TestImplementationDaoCRUD.my_cosinus.execution_plugin, TestImplementationDaoCRUD.my_cosinus.library_address)) res2 = ImplementationDao.find_from_definition( TestImplementationDaoCRUD.my_cosinus.name, TestImplementationDaoCRUD.my_cosinus.execution_plugin, TestImplementationDaoCRUD.my_cosinus.library_address) self.assertTrue( len(res2) == 1, "ImplementationDao.find_from_definition returns unique result") self.assertTrue( str(res) == str(res2[0]), "find_from_key <=> find_from_definition on same object") self.info("Found %s" % str(res2[0])) self.info("test_seq2_find [%s][%s][%s]" % (TestImplementationDaoCRUD.my_cosinus.name, TestImplementationDaoCRUD.my_cosinus.execution_plugin, TestImplementationDaoCRUD.my_cosinus.library_address))
def test_seq3_update(self): created_tan = ImplementationDao.create( TestImplementationDaoCRUD.my_tan) self.info( "After test_seq3_update: step 1 CREATE tan: ImplementationDao count = %s" % ImplementationDao.objects.count()) self.info("Original: %s" % created_tan.as_text()) created_tan.name = "TU ORM Python Standard tan" created_tan.output_profile = [TestImplementationDaoCRUD.res_three] updated_tan = ImplementationDao.update(created_tan) self.info("Updated: %s" % updated_tan.as_text())
def build_implem(self, the_implem, the_parent_algo=None, check_report=None, save=True): """ Complete implementation definition with parent algorithm. Perform checks on consistency. create a DAO record for given implementation on demand. :param the_implem: implementation to update :type the_implem: Implementation :param the_parent_algo: the parent algorithm, optional, default None :type the_parent_algo: Algorithm :param check_report: list of errors :type check_report: list :param save: boolean to save in db or not :type save: boolean :return: updated implementation :rtype: Implementation """ if the_parent_algo is not None: the_implem.algo = the_parent_algo if check_report is not None: self.__is_implementation_consistent(the_implem, check_report) self.__check_point(check_report) # Beware !!! risk to save without checking the consistency !!! if save is True: return ImplementationDao.create(the_implem) else: return the_implem
def test_to_dict(self): """ Tests the json-friendly python dict produced by to_dict() method on ImplementationWs instance: - Test made with TestWsCatalogue.my_cosinus """ bizz_impl = ImplementationDao.create(TestWsCatalogue.my_cosinus) ws_impl = ImplementationWs(bizz_impl) my_dict = ws_impl.to_dict() self.info(json.dumps(obj=my_dict, indent=2)) # reference hard-coded: id may be different ref_dict = { "is_customized": False, "outputs": [{ "type": None, "name": "result", "order_index": 0, "domain": None, "label": "result", "description": "cos(angle)" }], "parameters": [], "algo": None, "name": "TU WS Python Standard cosinus", "label": "TU WS Python Standard cosinus", "description": "Python cosinus from math::cos", "id": 11, "inputs": [{ "type": None, "name": "angle", "order_index": 0, "domain": None, "label": "angle", "description": "angle (rad)" }], "family": None, "visibility": True } self.assertTrue(type(my_dict) is dict) self.assertEqual(my_dict['id'], bizz_impl.db_id) self.assertEqual(my_dict['is_customized'], False) # correct ID before comparing ref_dict with my_dict ref_dict['id'] = my_dict['id'] self.assertDictEqual(my_dict, ref_dict, "my_dict differs from expected ref_dict")
def execute_algo_without_custom(implem, input_arg_names, input_data_sources, output_arg_names, output_data_receivers, exec_algo_db_id=None, run_debug=False, dao_managed=True): """ Firstly build the ExecutableAlgo: initialized without customized parameters in database (Custom DB is ignored) Secondly run the service FacadeExecution.execute_algo on created algo. :param implem: executed implementation :type implem: Implementation :param input_arg_names: complete list of input names :type input_arg_names: list :param input_data_sources: complete list of input values (either explicit values or DataSource subclasses) :type input_data_sources: list :param output_arg_names: complete list of output names :type output_arg_names: list :param output_data_receivers: complete list of output receivers: same length than output_arg_names: each element is either None or instance of DataReceiver subclass) :type output_data_receivers: list :param exec_algo_db_id: optional value of primary key of executable algorithm when it is already created, default is None. :type exec_algo_db_id: int :param run_debug: optional flag: True when debug is activated. Default is False :type run_debug: bool :param dao_managed: optional flag: True when executable algorithm is managed in DB. Default is True :type dao_managed: bool :return: exec_algo, exec_status tuple: exec_algo is the initialized algorithm; exec_status is the execution status :rtype: exec_algo is apps.algo.execute.models.business.algo.ExecutableAlgo and exec_status is apps.algo.execute.models.business.exec_engine.ExecStatus """ # executable algo building if isinstance(implem, str): my_implementation = ImplementationDao.find_business_elem_with_key( implem) else: my_implementation = implem my_exec_algo = FacadeExecution.factory.build_exec_algo_without_custom( implementation=my_implementation, input_names=input_arg_names, input_values_or_sources=input_data_sources, output_names=output_arg_names, output_receivers=output_data_receivers) # in case exec algo already defined in DB (asynchronous execution) if exec_algo_db_id is not None: # set algorithm db id my_exec_algo.set_process_id(exec_algo_db_id) return FacadeExecution.execute_algo(executable_algo=my_exec_algo, debug=run_debug, dao_managed=dao_managed)
def test_seq1_create(self): self.info("TestImplementationDaoCRUD::test_seq1_create") created_sinus = ImplementationDao.create( TestImplementationDaoCRUD.my_sinus) TestImplementationDaoCRUD.my_created_sinus = created_sinus self.info("After test_seq1_create: ImplementationDao count = %s" % ImplementationDao.objects.count()) self.info("Original %s" % str(TestImplementationDaoCRUD.my_sinus)) self.info("Created %s" % str(created_sinus))
def get_impl_id(self, name): """ Tests the implementation id returned """ my_resampling_impl = ImplementationDao.find_business_elem_with_name( name) self.assertIsNotNone( my_resampling_impl, "Not None: find Implementations list with name=" + name) self.assertEqual(len(my_resampling_impl), 1, "Unique Implementation with name=" + name) self.assertIsNotNone(my_resampling_impl[0].db_id, "ID of implementation with name=" + name) str_algo_id = str(my_resampling_impl[0].db_id) return str_algo_id
def setUpTestData(cls): """ setUpClass: this setup is made once for several tests_ methods operational database is not impacted by the Django unittests """ cls.init_logger() cls.info("Start: setUpTestData on TestCustomizedParameter") try: arg_one = Argument("angle", "angle (rad)", ProfileItem.DIR.INPUT, 0) param_factor = Parameter("factor", "factor on angle", ProfileItem.DIR.INPUT, 1) param_phase = Parameter(name="phase", description="added phase constant", direction=ProfileItem.DIR.INPUT, order_index=2, db_id=None, data_format="number", domain_of_values=None, label="phase", default_value="0") cls.res_one = Argument("result", "cos(angle)", ProfileItem.DIR.OUTPUT, 0) cls.res_two = Argument("result", "sin(angle)", ProfileItem.DIR.OUTPUT, 0) cls.res_three = Argument("result", "tan(angle)", ProfileItem.DIR.OUTPUT, 0) res_four = Argument("result", "tan(factor*angle+phase)", ProfileItem.DIR.OUTPUT, 0) cls.my_pseudo_impl = Implementation( "TU ORM impl for CustomizedAlgo", "Python tan from math::my_tan", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::my_tan_tri", [arg_one, param_factor, param_phase], [res_four]) # Implementation created in DB => this one will be tested # cls.my_pseudo_impl_from_db = ImplementationDao.create(cls.my_pseudo_impl) cls.my_arg_one = cls.my_pseudo_impl_from_db.find_by_name_input_item("angle") cls.my_param_factor = cls.my_pseudo_impl_from_db.find_by_name_input_item("factor") cls.my_param_phase = cls.my_pseudo_impl_from_db.find_by_name_input_item("phase") cls.info("setUpTestData initialized implem= {}".format(cls.my_pseudo_impl_from_db)) cls.info("setUpTestData initialized arg_one= {}".format(cls.my_arg_one)) cls.info("setUpTestData initialized param_factor= {}".format(cls.my_param_factor)) cls.info("setUpTestData initialized param_phase= {}".format(cls.my_param_phase)) except Exception as err: cls.logger().exception("got exception type=" + type(err).__name__) cls.logger().exception("exception as str=" + str(err)) cls.error("... ended setUpTestData TestCustomizedParameter: Failed: %s") cls.info("End: setUpTestData on TestCustomizedParameter")
def test_from_dict(self): """ Tests that ImplementationWs object is correctly loaded from a json-friendly dict """ # Prepare data ... bizz_impl = ImplementationDao.create(TestWsCatalogue.my_cosinus) ws_impl = ImplementationWs(bizz_impl) my_dict = ws_impl.to_dict() # ... apply load_from_dict loaded_ws_impl = ImplementationWs.load_from_dict(my_dict) # ... assert that loaded business is the same than bizz_impl loaded_bizz_impl = loaded_ws_impl.model_business self.assertTrue(loaded_bizz_impl == bizz_impl)
def get_implementation(http_request, id_implementation): """ Get the web service resource for ImplementationDao defined under the catalogue Example of requests: - "http://127.0.0.1:80/ikats/algo/catalogue/implementations/1" - "http://127.0.0.1:80/ikats/algo/catalogue/implementations/00001" :param http_request: request http :type http_request: django HttpQuery :param id_implementation: database primary key (number) :type id_implementation: str coding the integer value :return: implementationDao in a json format :rtype: JsonResponse """ response_builder = DjangoHttpResponseFactory() try: internal_id = int(id_implementation) business_obj = ImplementationDao.find_from_key(internal_id) if business_obj is None: return response_builder.get_json_response_not_found( "Implementation resource not found for id=%s" % str(internal_id)) ws_obj = ImplementationWs(business_obj) return JsonResponse(ws_obj.to_dict()) except Exception as err: LOGGER.exception(err) info = "WS: No such record: ImplementationDao id=%s" % ( id_implementation) LOGGER.error(info) return JsonResponse({ "error": { 'ikats_error': info, 'internal_error': ascii(str(err)) } })
def search_with_criteria(cls, implem_id=None, name=None, label=None, desc_content=None): """ Get the list of CustomizedAlgo matching the search specified by filtering criterion. Note: if no argument is defined: the complete list of CustomizedAlgo is returned. :param implem_id: optional default None: the Implementation db_id, defined when the search result is a list of CustomizedAlgo addressing such specific Implementation id. The argument implem_id. :type implem_id: str, None :param name: optional default None: criterion specifying searched name of the CustomizedAlgo :type name: str, None :param label: optional default None: criterion specifying searched label of the CustomizedAlgo :type label: str, None :param desc_content: optional default None: criterion specifying searched substring within the description of the CustomizedAlgo :type desc_content: str, None :return: the search result as a list :rtype: list """ my_query = CustomizedAlgoDao.objects.all() if implem_id is not None: my_implem_id = ImplementationDao.parse_dao_id(implem_id) my_query = my_query.filter(ref_implementation__id=my_implem_id) if name is not None: my_query = my_query.filter(name=name) if label is not None: my_query = my_query.filter(label=label) if desc_content is not None: my_query = my_query.filter(desc__contains=desc_content) result = [] for dao_resource in my_query: business_resource = dao_resource.build_business() result.append(business_resource) return result
def load_from_dict(cls, ws_dict): """ Reload the resource ImplementationWs with internal model: the 'id' key is required: points to existing Implementation from the catalogue DB. Restriction [#139805]: any other key of ws_dict is ignored, as the model is a read-only catalogue resource via ImplementationWs. :param cls: :type cls: :param ws_dict: :type ws_dict: """ my_implem_id = ws_dict.get('id', None) if my_implem_id is not None: business_implem = ImplementationDao.find_business_elem_with_key(primary_key=my_implem_id) else: raise IkatsException("Unexpected: missing Implementation reference from json ImplementationWs") return ImplementationWs(business_implem)
def prepare_catalogue_data(cls): """ this setup is made once for several tests_ methods operational database is not impacted by the Django unittests """ cls.init_logger() if cls.cat_initialized is False: cls.cat_initialized = True cls.info("Start: prepareCatalogueData on {}".format(cls.__name__)) t_name = cls.__name__ try: my_fam = FunctionalFamily(name=t_name + " tested family", description="", db_id=None, label="lab family") my_algo = Algorithm(name=t_name + "my algo", description=" desc", db_id=None, label="lab", family=my_fam) cls.arg_one = Argument("angle", "angle (rad)", ProfileItem.DIR.INPUT, 0) cls.param_factor = Parameter("factor", "factor on angle", ProfileItem.DIR.INPUT, 1) cls.param_factor.data_format = "number" cls.param_phase = Parameter(name="phase", description="added phase constant", direction=ProfileItem.DIR.INPUT, order_index=2, db_id=None, data_format="number", domain_of_values=None, label="phase", default_value=0) cls.param_phase_with_domain = Parameter( name="phase", description="added phase constant", direction=ProfileItem.DIR.INPUT, order_index=2, db_id=None, data_format="number", domain_of_values="[0, 1.1, 2 ]", label="phase with constraint", default_value=0) cls.res_one = Argument("result", "cos(angle)", ProfileItem.DIR.OUTPUT, 0) cls.res_two = Argument("result", "sin(angle)", ProfileItem.DIR.OUTPUT, 0) cls.res_three = Argument("result", "tan(angle)", ProfileItem.DIR.OUTPUT, 0) cls.res_four = Argument("result", "tan(factor*angle+phase)", ProfileItem.DIR.OUTPUT, 0) cls.my_cosinus = Implementation( t_name + " ORM Python Standard cosinus", "Python cosinus from math::cos", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::cos", [cls.arg_one], [cls.res_one]) cls.my_sinus = Implementation( t_name + " ORM Python Standard sinus", "Python sinus from math::sin", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::sin", [cls.arg_one], [cls.res_two]) cls.my_tan = Implementation( t_name + " ORM Python Standard tan", "Python tan from math::tan", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::tan", [cls.arg_one], [cls.res_three]) cls.my_pseudo_impl = Implementation( t_name + " ORM impl for CustomizedAlgo", "Python tan from math::my_tan", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "ikats.processing.ikats_processing.tests.test_contrib::my_tan", [cls.arg_one, cls.param_factor, cls.param_phase], [cls.res_four], algo=my_algo) cls.my_pseudo_impl_with_domain = Implementation( t_name + " ORM impl2 for CustomizedAlgo", "Python tan from math::my_tan_bis", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "ikats.processing.ikats_processing.tests.test_contrib::my_tan_bis", [ cls.arg_one, cls.param_factor, cls.param_phase_with_domain ], [cls.res_four], algo=my_algo) # Implementation created in DB => this one will be tested # cls.my_pseudo_impl_from_db = ImplementationDao.create( cls.my_pseudo_impl) cls.my_arg_one = cls.my_pseudo_impl_from_db.find_by_name_input_item( "angle") cls.my_param_factor = cls.my_pseudo_impl_from_db.find_by_name_input_item( "factor") cls.my_param_phase = cls.my_pseudo_impl_from_db.find_by_name_input_item( "phase") cls.info( "prepare_catalogue_data initialized implem= {}".format( cls.my_pseudo_impl_from_db)) cls.info( "prepare_catalogue_data initialized arg_one= {}".format( cls.my_arg_one)) cls.info("prepare_catalogue_data initialized param_factor= {}". format(cls.my_param_factor)) cls.info("prepare_catalogue_data initialized param_phase= {}". format(cls.my_param_phase)) cls.my_pseudo_impl_with_domain_from_db = ImplementationDao.create( cls.my_pseudo_impl_with_domain) cls.my_arg_one_bis = cls.my_pseudo_impl_with_domain_from_db.find_by_name_input_item( "angle") cls.my_param_factor_bis = cls.my_pseudo_impl_with_domain_from_db.find_by_name_input_item( "factor") cls.my_param_phase_bis = cls.my_pseudo_impl_with_domain_from_db.find_by_name_input_item( "phase") cls.info( "prepare_catalogue_data my_pseudo_impl_with_domain_from_db= {}" .format(cls.my_pseudo_impl_with_domain_from_db)) cls.info("prepare_catalogue_data my_arg_one_bis= {}".format( cls.my_arg_one_bis)) cls.info( "prepare_catalogue_data my_param_factor_bis= {}".format( cls.my_param_factor_bis)) cls.info( "prepare_catalogue_data my_param_phase_bis= {}".format( cls.my_param_phase_bis)) cls.info("End: prepare_catalogue_data on {}".format( cls.__name__)) except Exception as err: cls.logger().exception("got exception type=" + type(err).__name__) cls.logger().exception("exception as str=" + str(err)) cls.error("... ended prepare_catalogue_data {}: Failed".format( cls.__name__))
def load_from_dict(cls, ws_dict): """ Reload the resource CustomizedAlgoWs from the json-friendly dictionary ws_dict. This service checks the consistency against the catalogue+custom database definitions: - the ws_dict must match one Implementation in the catalogue database, identified by ws_dict['parent']['id'] - when the ws_dict['id'] is not None: it matches one CustomizedAlgo in the custom database - the customized values of parameters must match existing parameter definition in the target implementation. :param cls: :type cls: :param ws_dict: the json-friendly dictionary :type ws_dict: dict """ # my_parent_id, my_custo_id are string, independent of DAO choices (numbers handled by postgres) # When defined: my_parent_id is the ID of Implementation being customized my_parent_id = "" # When defined: my_custo_id is ID of customized algo in custom database my_custo_id = "" my_parent = ws_dict.get('parent', None) try: if my_parent is None: cls.raise_load_error( IkatsInputError, "missing definition of ws_dict['parent'] => unknown Implementation" ) else: my_parent_id = my_parent.get('id', None) if my_parent_id is None: cls.raise_load_error( IkatsInputError, "missing definition of ws_dict['parent']['id'] => unknown Implementation" ) my_implementation = ImplementationDao.find_business_elem_with_key( primary_key=my_parent_id) my_custo_id = ws_dict.get('id', None) # Get customized parameters my_custom_params = [] my_parameters_list = ws_dict.get('parameters', []) for param_dict in my_parameters_list: name = param_dict.get('name', None) if name is None: cls.raise_load_error( IkatsInputError, "Missing name on parameter: {}".format(param_dict)) if 'value' in param_dict.keys(): # Checks that referenced parameter is defined in catalogue cat_param = my_implementation.find_by_name_input_item( name, Parameter) if cat_param is None: msg = "Unmatched parameter name={} for implementation id={}" cls.raise_load_error( IkatsInputError, msg.format(name, my_parent_id)) parsed_val = param_dict['value'] custo_param = CustomizedParameter( cat_param, parsed_val) my_custom_params.append(custo_param) if len(my_custom_params) == 0: cls.raise_load_error( IkatsInputError, "CustomizedAlgo must have at least one customized value" ) if my_custo_id is not None: # We just check that the defined id is matching one resource in the database # - if missing => raises CustomizedAlgoDao.DoesNotExist CustomizedAlgoDao.find_business_elem_with_key( primary_key=my_custo_id) my_name = ws_dict.get('name', None) my_label = ws_dict.get('label', my_name) my_desc = ws_dict.get('description', None) business_custo_algo = CustomizedAlgo( arg_implementation=my_implementation, custom_params=my_custom_params, name=my_name, label=my_label, db_id=my_custo_id, description=my_desc) return CustomizedAlgoWs(business_custo_algo) except ImplementationDao.DoesNotExist: cls.raise_load_error( IkatsNotFoundError, "Not found: Implementation with id={}".format(my_parent_id)) except CustomizedAlgoDao.DoesNotExist: cls.raise_load_error( IkatsNotFoundError, "Not found: CustomizedAlgo with id={}".format(my_custo_id)) except IkatsException as e: raise e except Exception as err: cls.raise_load_error(IkatsException, str(err))
def find_custom_algos_for_implem(http_request, implementation_id): """ Finds all customized algo which are customizing specified implementation. :param http_request: the django request built by custom app, driven by its urls.py :type http_request: HttpRequest :param implementation_id: the identifier of the implementation :type implementation_id: int or parsable str :return: the Json response (nominal or error). :rtype: JsonResponse """ # Rejecting not allowed method cases: POST, PUT or DELETE if http_request.method != 'GET': return not_allowed_method(http_request) # ... dealing with the expected GET method # # Will help to build the response in try: or except: bodies response_builder = DjangoHttpResponseFactory() # Returned object my_response = None try: query_dict = http_request.GET # info-level is used to adapt the returned content of resource my_level = HttpCommonsIkats.get_info_level(http_request, query_dict, default=LevelInfo.SUMMARY) business_list = CustomFacade.search_with_criteria( implem_id=implementation_id) if len(business_list) > 0: ids = [x.db_id for x in business_list] LOG_WS_CUSTOM.info( "Found customized algo versions %s of implementation id=%s", ids, implementation_id) serializable_list = CustomJsonFacade.convert_to_ws_list_custom_algo( business_list, level=my_level) my_response = JsonResponse(serializable_list, safe=False) elif len(business_list) == 0: my_implem_key = ImplementationDao.parse_dao_id(implementation_id) try: ImplementationDao.find_business_elem_with_key( primary_key=my_implem_key) LOG_WS_CUSTOM.info( "Does not exist: customized algo of implementation id=%s", implementation_id) my_response = JsonResponse([], safe=False) except ImplementationDao.DoesNotExist: # Example: implementation_id does not exist in database msg = "Unknown Implementation ID={} occurred in find_custom_algos_for_implem" msg = msg.format(implementation_id) LOG_WS_CUSTOM.error(msg) my_response = response_builder.get_json_response_not_found( ikats_error=msg) except IkatsInputError as err: # Example: invalid info_level value in query params ... LOG_WS_CUSTOM.exception(err) msg = "Bad request in find_custom_algos_for_implem with id={}".format( implementation_id) LOG_WS_CUSTOM.error(msg) my_response = response_builder.get_json_response_bad_request( ikats_error=msg, exception=err) except Exception as err: # Example: database is down LOG_WS_CUSTOM.exception(err) msg = "Unexpected server error in find_custom_algos_for_implem with id={}".format( implementation_id) LOG_WS_CUSTOM.error(msg) my_response = response_builder.get_json_response_internal_server_error( ikats_error=msg) # Finally returned: nominal response or error response return my_response
def run(algo_name, arg_names, arg_values, asynchro=False, is_customized_algo=False, run_debug=True): """ Launch the algorithm for the specified Implementation/CustomizedAlgo :param algo_name: the ID is matching an Implementation or a CustomizedAlgo according to the flag is_customized_algo :type algo_name: str :param arg_names: list of input names :type arg_names: list of string :param arg_values: list of input arguments values matching arg_names :type arg_values: list :param is_customized_algo: True if algo_name identifies CustomizedAlgo, otherwise False if algo_name identifies an Implementation :type is_customized_algo: boolean :param run_debug: TODO :type run_debug: boolean :return: <status> sums up the execution status: | You can get from status the process ID, the (error) message etc. : see ExecutionStatus documentation. :rtype: apps.algo.execute.models.business.exec_status.ExecutionStatus """ engine_status = ExecStatus(debug=run_debug, msg="Initial status before starting the execution engine") execution_status = ExecutionStatus(algo=None, internal_status=engine_status) my_script_name = "RunAlgo" msg = "Execute: %s , arg_names=%s" % (my_script_name, str(arg_names)) # status is set to default value # in case of unexpected error in FacadeExecution.execute below execution_status.add_msg(msg) if len(arg_names) != len(arg_values): msg = 'Argument error in execalgo.run: incorrect arguments number)' execution_status.set_error_with_msg(IkatsInputError(msg), "RunAlgo: initial check failed") # CheckEngine status generated when check have been applied status = None try: if is_customized_algo: my_custom = CustomizedAlgoDao.find_business_elem_with_name(algo_name)[0] # ... may raise CustomizedAlgoDao.DoesNotExist my_implementation = my_custom.implementation else: my_custom = None my_implementation = ImplementationDao.find_business_elem_with_name(algo_name)[0] # ... may raise ImplementationDao.DoesNotExist my_script_name = my_script_name + " on " + my_implementation.name def_resource = __get_run_definition(implementation=my_implementation, customized_algo=my_custom) context = "Run algo with args {} on {}".format(json.dumps(__get_run_args(arg_names, arg_values)), def_resource) checker = CheckEngine(checked_resource=def_resource, checked_value_context=context, check_status=None) completed_arg_names, completed_data_sources, output_names, receivers = __prepare_execution( algo_name, arg_names, arg_values, execution_status, my_implementation, my_custom, checker) if checker.has_errors(): # ExecutableAlgo is not created, not executed raise CheckError(msg=context, status=checker.get_check_status()) if asynchro is True: # asynchronous execution # creation of an executable algorithm DAO in order to get an id exec_algo = FacadeExecution.factory.build_exec_algo_without_custom_without_data_connectors( my_implementation) # business object is updated with db_id created by DAO exec_algo = ExecutableAlgoDao.create(exec_algo, False) execution_status.set_algo(exec_algo) exec_algo_db_id = exec_algo.get_process_id() # Create a thread for the algorithm execution itself run_msg = "Running asynchronous: {0} with implementation={1}".format(my_script_name, my_implementation.name) LOGGER.info(run_msg) execution_status.add_msg(run_msg) threading.Thread(target=FacadeExecution.execute_algo_without_custom, args=(my_implementation, completed_arg_names, completed_data_sources, output_names, receivers, "" + exec_algo_db_id, run_debug, True)).start() else: # synchronous execution run_msg = "Running synchronous: {0} with implementation={1}".format(my_script_name, my_implementation.name) LOGGER.info(run_msg) execution_status.add_msg(run_msg) exec_algo, status = FacadeExecution.execute_algo_without_custom( implem=my_implementation, input_arg_names=completed_arg_names, input_data_sources=completed_data_sources, output_arg_names=output_names, output_data_receivers=receivers, exec_algo_db_id=None, run_debug=run_debug, dao_managed=True) execution_status.set_algo(exec_algo) # replace local internal status by the engine status: more interesting execution_status.set_internal_status(status) run_msg = "Ran synchronous: {0} with implementation={1}".format(my_script_name, my_implementation.name) execution_status.add_msg(run_msg) LOGGER.info(run_msg) except CustomizedAlgoDao.DoesNotExist as cerr: nf_msg = "Argument error in execalgo.run: unmatched CustomizedAlgo: err={}".format(cerr) nf_err = IkatsNotFoundError(nf_msg) execution_status.set_error_with_msg(nf_err, "RunAlgo: initial check failed") except ImplementationDao.DoesNotExist as ierr: nf_msg = "Argument error in execalgo.run: unmatched Implementation: err={}".format(ierr) nf_err = IkatsNotFoundError(nf_msg) execution_status.set_error_with_msg(nf_err, "RunAlgo: initial check failed") except (CheckError, IkatsInputError, IkatsNotFoundError, IkatsException) as exception: # interrupts the executions # => in that case: executable algo is not created ... raise exception except Exception as error: error_message = "Failure occurred running {0} with implementation={1}".format( my_script_name, algo_name) LOGGER.error(error_message) execution_status.add_msg(error_message) LOGGER.exception(error) if (status is None) or (not status.has_error()): # add error when not yet recorded ... msg = "Unexpected error occurred" execution_status.get_state().set_error_with_msg(added_error=error, added_msg=msg, raise_error=False) execution_status.get_state().debug = True # logged by calling code # Note that at this step: execution_status.has_error() may be true return execution_status
def test_seq6_delete(self): fam_count_before = FunctionalFamilyDao.objects.count() algo_count_before = AlgorithmDao.objects.count() impl_count_before = ImplementationDao.objects.count() prof_count_before = ProfileItemDao.objects.count() self.info("Pre-condition: FunctionalFamilyDao count = %s" % fam_count_before) self.info("Pre-condition: AlgorithmDao count = %s" % algo_count_before) self.info("Pre-condition: ImplementationDao count = %s" % impl_count_before) self.info("Pre-condition: ProfileItemDao count = %s" % prof_count_before) step = "------ step 1: create tan Tri ------" self.info(step) family = FunctionalFamilyDao.create( FunctionalFamily(name="TU family", description="TU family for tan Tri")) algo = AlgorithmDao.create( Algorithm(name="TU algo", description="desc TU algo", label="label", family=family)) self.info(" - family: %s" % str(family)) self.info(" - algo: %s" % str(algo)) fam_count_step1 = FunctionalFamilyDao.objects.count() algo_count_step1 = AlgorithmDao.objects.count() self.info("Parent family created: FunctionalFamilyDao count = %s" % fam_count_step1) self.info("Parent algo created: AlgorithmDao count = %s" % algo_count_step1) tan_tri = Implementation( "TU ORM Python Standard tan TRI", "Python tan TRI from math::tan", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::tan", [TestImplementationDaoCRUD.arg_one], [TestImplementationDaoCRUD.res_three]) tan_tri.algo = algo created_tan = ImplementationDao.create(tan_tri) impl_count_step1 = ImplementationDao.objects.count() prof_count_step1 = ProfileItemDao.objects.count() self.info("Once tan Tri created: ImplementationDao count = %s" % impl_count_step1) self.info("Once tan Tri created: ProfileItemDao count = %s" % prof_count_step1) self.info(" - Original tan Tri oper: %s" % str(tan_tri)) self.info(" - Created tan Tri oper: %s" % str(created_tan)) step = "------ step 2: delete oper tan Tri with parent algo ------" self.info(step) ImplementationDao.delete_resource(created_tan) fam_count_step2 = FunctionalFamilyDao.objects.count() algo_count_step2 = AlgorithmDao.objects.count() impl_count_step2 = ImplementationDao.objects.count() prof_count_step2 = ProfileItemDao.objects.count() self.info( "Step2: once tan Tri deleted: FunctionalFamilyDao count = %s" % fam_count_step2) self.info("Step2: once tan Tri deleted: AlgorithmDao count = %s" % algo_count_step2) self.info("Step2: once tan Tri deleted: ImplementationDao count = %s" % impl_count_step2) self.info("Step2: once tan Tri deleted: ProfileItemDao count = %s" % prof_count_step2) self.assertEqual( fam_count_step2, fam_count_step1, "After delete: family count unchanged: fam_count_step2 == fam_count_step1" ) self.assertEqual( algo_count_step2, algo_count_step1, "After delete: algo count unchanged: algo_count_step2 == algo_count_step1" ) self.assertEqual( impl_count_step2, impl_count_before, "After delete: impl_count_step2 == impl_count_before") self.assertEqual( prof_count_step2, prof_count_before, "After second delete: prof_count_step2 == prof_count_before") self.assertTrue(impl_count_step2 < impl_count_step1) self.assertTrue(prof_count_step2 < prof_count_step1)
def test_seq5_delete(self): impl_count_before = ImplementationDao.objects.count() prof_count_before = ProfileItemDao.objects.count() self.info("Pre-condition: ImplementationDao count = %s" % impl_count_before) self.info("Pre-condition: ProfileItemDao count = %s" % prof_count_before) step = "------ step 1: create tan + tan Bis ------" self.info(step) created_tan = ImplementationDao.create( TestImplementationDaoCRUD.my_tan) impl_count_step1_1 = ImplementationDao.objects.count() prof_count_step1_1 = ProfileItemDao.objects.count() self.info("Once tan created: ImplementationDao count = %s" % impl_count_step1_1) self.info("Once tan created: ProfileItemDao count = %s" % prof_count_step1_1) self.info(" created input: " + str(created_tan.input_profile[0])) self.info(" created output: " + str(created_tan.output_profile[0])) tan_bis = Implementation( "TU ORM Python Standard tan BIS", "Python tan BIS from math::tan", "apps.algo.execute.models.business.python_local_exec_engine::PythonLocalExecEngine", "math::tan", [created_tan.input_profile[0]], [created_tan.output_profile[0]]) created_tan_bis = ImplementationDao.create(tan_bis) impl_count_step1_2 = ImplementationDao.objects.count() prof_count_step1_2 = ProfileItemDao.objects.count() self.info("Once tan Bis created: ImplementationDao count = %s" % impl_count_step1_2) self.info("Once tan Bis created: ProfileItemDao count = %s" % prof_count_step1_2) self.info(" - Original tan oper: %s" % str(TestImplementationDaoCRUD.my_tan)) self.info(" - Created tan oper: %s" % str(created_tan)) self.info(" - Created tan BIS oper: %s" % str(created_tan_bis)) step = "------ step 2: delete oper tan with shared Profile_Items ------" self.info(step) ImplementationDao.delete_resource(created_tan) impl_count_step2 = ImplementationDao.objects.count() prof_count_step2 = ProfileItemDao.objects.count() self.info("Once tan deleted: ImplementationDao count = %s" % impl_count_step2) self.info("Once tan deleted: ProfileItemDao count = %s" % prof_count_step2) self.assertEqual( impl_count_step1_2, impl_count_step2 + 1, "After first delete: impl_count_step2 == impl_count_step2 +1") self.assertEqual( prof_count_step1_2, prof_count_step2, "After first delete: no orphan profile_item: prof_count_step1_2 == prof_count_step2" ) step = "------ step 3: delete oper tan BIS with no more shared Profile_Items ------" self.info(step) ImplementationDao.delete_resource(created_tan_bis) impl_count_step3 = ImplementationDao.objects.count() prof_count_step3 = ProfileItemDao.objects.count() self.info("Once tan Bis deleted: ImplementationDao count = %s" % impl_count_step3) self.info("Once tan Bis deleted: ProfileItemDao count = %s" % prof_count_step3) self.assertEqual( impl_count_step3, impl_count_before, "After second delete: impl_count_step3 == impl_count_before") self.assertEqual( prof_count_step3, prof_count_before, "After second delete: prof_count_step3 == prof_count_before")