diff --git a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py index f15e9009..8a187c22 100755 --- a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -648,7 +648,7 @@ def OrchestratorRerunAsAdmin(): else: print(f"Уже запущено с правами администратора!") -def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSettingsStr = None, inAsyncInitBool = False): +def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSettingsStr = None, inAsyncInitBool = False, inPackageLevelInt = 0): """L+,W+: Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов) Добавляет инициализированный модуль в пространство sys.modules как imported (имя модуля = имя файла без расширения). @@ -678,18 +678,30 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet :param inDefStr: ОПЦИОНАЛЬНО Строковое наименование функции. Преимущественно для обратной совместимости :param inDefArgNameGSettingsStr: ОПЦИОНАЛЬНО Наименование аргумента, в который требуется передать GSettings (если необходимо) :param inAsyncInitBool: ОПЦИОНАЛЬНО True - Инициализация py модулей в отдельных параллельных потоках - псевдопараллельное выполнение. False - последовательная инициализация + :param inPackageLevelInt: ОПЦИОНАЛЬНО Уровень вложенности модуля в пакет. По умолчанию 0 (не является модулем пакета) :return: Сведения об инициализированных модулях в структуре: { "ModuleNameStr":{"PyPathStr": "", "Module": ...}, ...} """ inGlobPatternStr = CrossOS.PathStr(inGlobPatternStr) + # # # # # # # # - def __execute__(inResultDict, inPyPathItemStr, inDefStr = None, inDefArgNameGSettingsStr = None): + def __execute__(inResultDict, inPyPathItemStr, inDefStr = None, inDefArgNameGSettingsStr = None, inPackageLevelInt=0): try: lPyPathItemStr = inPyPathItemStr + CrossOS.PathSplitList(inPathStr=lPyPathItemStr)[-1*inPackageLevelInt-1:-1] lModuleNameStr = os.path.basename(lPyPathItemStr)[0:-3] - lTechSpecification = importlib.util.spec_from_file_location(lModuleNameStr, lPyPathItemStr) - lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) - sys.modules[lModuleNameStr] = lTechModuleFromSpec # Add initialized module in sys - python will not init this module enought - lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) + if inPackageLevelInt==0: + lTechSpecification = importlib.util.spec_from_file_location(lModuleNameStr, lPyPathItemStr) + lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) + sys.modules[lModuleNameStr] = lTechModuleFromSpec # Add initialized module in sys - python will not init this module enought + lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) + else: + lPrePackagePathStr=CrossOS.PathStr("\\".join(CrossOS.PathSplitList(inPathStr=lPyPathItemStr)[:-1-inPackageLevelInt])) + lPackageNameStr=".".join(CrossOS.PathSplitList(inPathStr=lPyPathItemStr)[-inPackageLevelInt-1:-1]) + lModuleNameStr=os.path.basename(lPyPathItemStr)[0:-3] + sys.path.insert(0,lPrePackagePathStr) + lTechSpecification = importlib.import_module(f".{lModuleNameStr}", lPackageNameStr) + lTechModuleFromSpec=sys.modules[f"{lPackageNameStr}.{lModuleNameStr}"] + lModuleNameStr= f"{lPackageNameStr}.{lModuleNameStr}" lItemDict = {"ModuleNameStr": lModuleNameStr, "PyPathStr": lPyPathItemStr, "Module": lTechModuleFromSpec} if lL: lL.info(f"Модуль .py {lModuleNameStr} был успешно инициализирован. Путь к файлу: {lPyPathItemStr}") inResultDict[lModuleNameStr]=lItemDict @@ -713,12 +725,12 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet # ASYNC EXECUTION lThreadInit = threading.Thread(target=__execute__,kwargs={ "inResultDict":lResultDict, "inPyPathItemStr": lPyPathItemStr, - "inDefStr": inDefStr, "inDefArgNameGSettingsStr": inDefArgNameGSettingsStr}, daemon=True) + "inDefStr": inDefStr, "inDefArgNameGSettingsStr": inDefArgNameGSettingsStr, "inPackageLevelInt":inPackageLevelInt}, daemon=True) lThreadInit.setName("PY_SEARCH_MODULE_INIT") lThreadInit.start() else: # SYNC EXECUTION - __execute__(inResultDict=lResultDict, inPyPathItemStr=lPyPathItemStr, inDefStr = inDefStr, inDefArgNameGSettingsStr = inDefArgNameGSettingsStr) + __execute__(inResultDict=lResultDict, inPyPathItemStr=lPyPathItemStr, inDefStr = inDefStr, inDefArgNameGSettingsStr = inDefArgNameGSettingsStr, inPackageLevelInt=inPackageLevelInt) return lResultDict def OrchestratorSessionSave(inGSettings=None): diff --git a/changelog.md b/changelog.md index ccbfcb22..626a5ef6 100755 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ AGT - AGENT [1.3.1] - ОРКЕСТРАТОР - минорные правки в дизайн +- Orchestrator.OrchestratorPySearchInit - добавлена возможность импорта пакетов с импользованием relative imports внутри - СТУДИЯ - - UI переведен на русский язык - - обновлен дизайн по аналогии с порталом и Оркестратором