...
Остановить работу приложения:
Блок кода service polymatica stop
Убедиться, что в файле конфигурации утилиты plm-util.conf указан параметр, определяющий путь до репозитория Polymatica Analytics, обычно это
/var/plmrepo
:Блок кода language bash plm.manager.repo_directory = /var/plmrepo
Создать в системе хоста приложения директорию /var/plmrepo/pyscripts/директория_python-скрипта, создать в ней файл с расширением .py и вставить в него код скрипта. Например:
Блок кода /var/plmrepo/pyscripts/drill_through_on_population_ms/script.py
Блок кода language py title Разверните блок и скопируйте код linenumbers true collapse true import argparse import json import logging import os import sys from typing import List def err(err_type: str, msg: str): json.dump({"type": err_type, "message": msg}, sys.stderr, ensure_ascii=False) sys.exit(1) try: from polymatica import business_scenarios from polymatica.exceptions import PolymaticaException, RightsError, ScenarioError except ImportError: err(err_type="polyapi", msg="polyapi no installed") sys.stdout = open(1, "w", encoding='utf-8', closefd=False) ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) print("script args: ", sys.argv[1:]) class KeyValue(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, dict()) for value in values: key, value = value.split('=') getattr(namespace, self.dest)[key] = value class LoggerDisabler: """ Контекстный менеджер, временно отключающий логгирование, чтобы ошибки из полиапи не попадали напрямую в stderr, так как они передаются в этот скрипт и через функцию err попадают в stderr внутри json. """ def __enter__(self): logging.disable(logging.ERROR) def __exit__(self, exc_type, exc_val, exc_tb): logging.disable(logging.NOTSET) parser = argparse.ArgumentParser() parser.add_argument('--dimension-elements', nargs='*', action=KeyValue) parser.add_argument('--connection_session', nargs=3) parser.add_argument('--url') parser.add_argument('--layer_id') parser.add_argument('--scenario_id') parser.add_argument('--cube_id') parser.add_argument('--config_path', default=os.path.join(ROOT_PATH, 'config.json')) args = parser.parse_args() print("dim args: ", args.dimension_elements) class DimFilter: def __init__(self, dim_id: str, filter_val: str): self.dim_id = dim_id self.filter_val = filter_val class MapInfo: def __init__(self, scenario_id: str, cube_id: str, filters: List[DimFilter]): self.scenario_id = scenario_id # 1. запустить self.cube_id = cube_id # 2. найти на слое мультисферы этого куба self.filters = filters # 3. применить к мультисферам def extract_map_info(cfg) -> MapInfo: for scenario_pair in cfg['scenarios']: from_sc_id = scenario_pair['from_scenario_id'] to_sc_id = scenario_pair['to_scenario_id'] if args.scenario_id == from_sc_id: dims_to_filter = [] to_cube_id = 0 for cube_pair in scenario_pair['cubes']: if cube_pair['from_cube_id'] == args.cube_id: to_cube_id = cube_pair['to_cube_id'] for dim in cube_pair['dimensions']: from_dim_id = dim['from_dimension_id'] to_dim_id = dim['to_dimension_id'] if from_dim_id in args.dimension_elements.keys(): dim_filter = DimFilter(dim_id=to_dim_id, filter_val=args.dimension_elements[from_dim_id].encode('utf8', 'surrogateescape').decode( 'utf8')) dims_to_filter.append(dim_filter) break return MapInfo(filters=dims_to_filter, cube_id=to_cube_id, scenario_id=to_sc_id) raise Exception("в конфиге не найдена пара сценариев") try: with open(args.config_path) as f: json_config = json.load(f) except OSError: err(err_type="os", msg="cannot open {}".format(args.config_path)) except json.JSONDecodeError as e: err(err_type="json", msg=str(e)) try: map_info = extract_map_info(json_config) except Exception as e: err(err_type="config", msg="Неверный формат конфига: {}".format(str(e))) if len(map_info.filters) != len(args.dimension_elements): err(err_type="config", msg="Пары для размерностей \"{}\" не заданы в конфиге".format(args.dimension_elements.keys())) try: session_params = {"session_id": args.connection_session[0], "manager_uuid": args.connection_session[1], "full_polymatica_version": args.connection_session[2]} with LoggerDisabler(): bs = business_scenarios.BusinessLogic("", session_auth=session_params, url=json_config['connection']['url']) except Exception as e: err(err_type="connect", msg=str(e)) print("starting scenario \"{}\" on layer \"{}\"".format(map_info.scenario_id, args.layer_id)) try: with LoggerDisabler(): bs._check_scenario_cubes_permission(scenario_id=map_info.scenario_id) if bs.check_scenarios_dims_facts_persmission(scenario_id=map_info.scenario_id): bs.run_scenario_on_layer(scenario_id=map_info.scenario_id, layer_id=args.layer_id) except RightsError as e: err(err_type="rights", msg="Не удалось запустить связанный сценарий: " + e.user_msg) except ScenarioError as e: err(err_type="scenario", msg="Не удалось запустить связанный сценарий: " + e.user_msg) except Exception as e: err(err_type="scenario", msg="Не удалось запустить связанный сценарий") print("scenario \"{}\" successfully finished on layer \"{}\"".format(map_info.scenario_id, args.layer_id)) modules_to_filter = [] for module_info in bs.get_module_list(): if module_info[3] == map_info.cube_id: modules_to_filter.append(module_info[0]) if len(modules_to_filter) == 0: err(err_type="module", msg="Не найден модуль созданный из куба с id \"{}\" в сценарии \"{}\"".format(map_info.cube_id, map_info.scenario_id)) def find_dim(dims_list, dim_id): for dim in dims_list: if dim.get('id', '') == dim_id: return dim return None for module_id in modules_to_filter: bs.set_multisphere_module_id(module_id) dims = bs._get_dimensions_list() for filter_to_put in map_info.filters: dim = find_dim(dims, filter_to_put.dim_id) if not dim: continue try: bs.put_dim_filter_by_value(dim_id=filter_to_put.dim_id, value=filter_to_put.filter_val, clear_filter=True) print( "putted filter with value - \"{}\" on dim with id - \"{}\"".format(filter_to_put.filter_val, filter_to_put.dim_id)) except PolymaticaException as e: # если фильтр исключен другим фильтром то игнорим его print( "skipped filter with value - \"{}\" on dim with id - \"{}\"".format(filter_to_put.filter_val, filter_to_put.dim_id))
...