From 760e1020d3be56b07be343d5ffcc83ae1e78f94e Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Thu, 7 Jul 2022 18:00:06 +0300 Subject: [PATCH] Add Tools.Template for work with Jinja2 (need for Studio + Orchestrator web index page) --- .../Orchestrator/Managers/ControlPanel.py | 9 +- Sources/pyOpenRPA/Tools/CrossOS.py | 24 +++- Sources/pyOpenRPA/Tools/Template.py | 127 ++++++++++++++++++ changelog.md | 11 ++ 4 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 Sources/pyOpenRPA/Tools/Template.py diff --git a/Sources/pyOpenRPA/Orchestrator/Managers/ControlPanel.py b/Sources/pyOpenRPA/Orchestrator/Managers/ControlPanel.py index 599eed11..c6602fe3 100644 --- a/Sources/pyOpenRPA/Orchestrator/Managers/ControlPanel.py +++ b/Sources/pyOpenRPA/Orchestrator/Managers/ControlPanel.py @@ -5,6 +5,7 @@ from inspect import signature # For detect count of def args from ..Web import Basic import operator import math +from pyOpenRPA.Tools import CrossOS class ControlPanel(): """ @@ -108,8 +109,8 @@ class ControlPanel(): """ try: if inJinja2TemplatePathStr is not None: - lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1]) - lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1] + lSystemLoaderPathStr = "/".join(CrossOS.PathSplitList(inPathStr=inJinja2TemplatePathStr)[0:-1]) + lTemplateFileNameStr = CrossOS.PathSplitList(inPathStr=inJinja2TemplatePathStr)[-1] self.mRefreshHTMLJinja2TemplateFileNameStr = lTemplateFileNameStr self.mRefreshHTMLJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr) self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True) @@ -137,8 +138,8 @@ class ControlPanel(): """ try: if inJinja2TemplatePathStr is not None: - lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1]) - lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1] + lSystemLoaderPathStr = "/".join(CrossOS.PathSplitList(inPathStr=inJinja2TemplatePathStr)[0:-1]) + lTemplateFileNameStr = CrossOS.PathSplitList(inPathStr=inJinja2TemplatePathStr)[-1] self.mInitJSJinja2TemplateFileNameStr = lTemplateFileNameStr self.mInitJSJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr) self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True) diff --git a/Sources/pyOpenRPA/Tools/CrossOS.py b/Sources/pyOpenRPA/Tools/CrossOS.py index 94f9654a..e3ca7223 100644 --- a/Sources/pyOpenRPA/Tools/CrossOS.py +++ b/Sources/pyOpenRPA/Tools/CrossOS.py @@ -16,7 +16,6 @@ def PathStr(inPathStr:str) -> str: .. code-block:: python - # Clipboard: Взаимодействие с буфером from pyOpenRPA.Tools import CrossOS lPathStr = CrossOS.PathStr(inPathStr = 'path/to\\file') # WINDOWS: lPathStr == 'path\\to\\file' @@ -30,4 +29,25 @@ def PathStr(inPathStr:str) -> str: if IS_WINDOWS_BOOL: return inPathStr.replace("/","\\") if IS_LINUX_BOOL: - return inPathStr.replace("\\","/") \ No newline at end of file + return inPathStr.replace("\\","/") + +def PathSplitList(inPathStr:str) -> list: + """Парсинг строки пути на элементы. Учитывает специфику формирования путей в разных ОС (Windows, Linux) + + Для Windows ОС: path\\to\\file + Для Linux ОС: path/to/file + + .. code-block:: python + + from pyOpenRPA.Tools import CrossOS + lPathList = CrossOS.PathSplitList(inPathStr = 'path/to\\file') + # WINDOWS: lPathList == ['path', 'to', 'file'] + # LINUX: lPathList == ['path', 'to', 'file'] + + :param inPathStr: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение + :type inPathStr: str + :return: Массив элементов пути. Пример: ['path', 'to', 'file'] + :rtype: list + """ + inPathStr = inPathStr.replace("\\","/") + return inPathStr.split("/") \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/Template.py b/Sources/pyOpenRPA/Tools/Template.py new file mode 100644 index 00000000..01360e09 --- /dev/null +++ b/Sources/pyOpenRPA/Tools/Template.py @@ -0,0 +1,127 @@ +from pyOpenRPA import Orchestrator +from . import CrossOS +import jinja2 +import os +from inspect import signature # For detect count of def args +import operator +import math +import copy + +class Template(): + """ + Шаблон генерации строки. Использует Jinja2 + + .. code-block:: python + + from pyOpenRPA.Tools import Template + # ПРИМЕР: + lTemplate = Template.Template( + inPathStr="ControlPanel\\test.html", + inRefreshBool = True) + lStr = lTemplate.GenerateStr() # Сформировать текст по шаблону + + Контектст, который формируется по умолчанию: + ControlPanelInstance: self, + OrchestratorModule: Orchestrator, + EnumerateDef: enumerate, + OperatorModule: operator, + MathModule: math + + Вы можете дополнить стандартный словарь контекста с помощью функции ContextDictSet() + + .. code-block:: html + + Hello my control panel! + You can use any def from Orchestrator module here in Jinja2 HTML template: + Example: OrchestratorModule.OSCMD(inCMDStr="notepad") + {{MathModule.pi}} + + """ + # Jinja2 consolidated + mJinja2TemplateRefreshBool = None + mJinja2ContextDict = None + mJinja2TemplatePathStr = None + mJinja2TemplateFileNameStr = None + mJinja2Loader = None + mJinja2Env = None + mJinja2Template = None + mLogger = None + + def __init__(self, inPathStr = None, inRefreshBool = False, inLogger = None): + """ + Конструктор шаблона для генерации + + :param inPathStr: Путь к шаблону. Поддерживает специфику разлных ОС. 'path/to/file' и 'path\\to\\file' + :param inRefreshBool: True - читать шаблон из файловой системы при каждом обращении на формирование строки (GenerateStr) + """ + self.PathSet(inPathStr = inPathStr) + self.mJinja2TemplateRefreshBool = inRefreshBool + self.mLogger = inLogger + + def ContextDictSet(self, inContextDict): + """ + Установить дополнительный контекст для генерации строки. + + :param inContextDict: Дополнительный контекст, который будет использоваться при формировании строки + """ + self.mJinja2ContextDict = inContextDict + + def PathSet(self, inPathStr): + """ + Установить путь к шаблону для генерации (движок Jinja2) + + :param inPathStr: Путь к шаблону для генерации + """ + try: + if inPathStr is not None: + lSystemLoaderPathStr = "/".join(CrossOS.PathSplitList(inPathStr=inPathStr)[0:-1]) + lTemplateFileNameStr = CrossOS.PathSplitList(inPathStr=inPathStr)[-1] + self.mJinja2TemplateFileNameStr = lTemplateFileNameStr + self.mJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr) + self.mJinja2Env = jinja2.Environment(loader=self.mJinja2Loader, trim_blocks=True) + self.mJinja2Template = self.mJinja2Env.get_template(lTemplateFileNameStr) + except Exception as e: + if self.mLogger: self.mLogger.exception("EXCEPTION WHEN INIT JINJA2") + raise e + + def GenerateStr(self, inContextDict=None): + """ + Сформировать строку с помощью шаблонизатора Jinja2. Передать контекст для формирования inContextDict. + + По умолчанию доступны следующие атрибуты контекста: + { + "TemplateInstance":self, + "OrchestratorModule":Orchestrator, + "EnumerateDef": enumerate, + "OperatorModule": operator, + "MathModule": math + } + + :param inContextDict: Дополнительный контекст для генерации строки. + :return: Сформированная строка + :rtype: str + """ + if inContextDict is None: inContextDict = {} + if self.mJinja2TemplateRefreshBool == True: + self.mJinja2Template = self.mJinja2Env.get_template(self.mJinja2TemplateFileNameStr) + lContextDict = self.ContextGenerateDict() + lContextDict.update(inContextDict) + lStr = self.mJinja2Template.render(**lContextDict) # Render the template into str + return lStr + + def ContextGenerateDict(self): + """ + Техническая функция. Сформировать преднастроенный словарь контекста для дальнейшего дообогащения + :return: + """ + lData = { + "TemplateInstance":self, + "OrchestratorModule":Orchestrator, + "EnumerateDef": enumerate, + "OperatorModule": operator, + "MathModule": math + } + # Checkj Jinja2ContextDict + if self.mJinja2ContextDict is not None: + lData.update(self.mJinja2ContextDict) + return lData \ No newline at end of file diff --git a/changelog.md b/changelog.md index 31f57309..9c1ddd07 100644 --- a/changelog.md +++ b/changelog.md @@ -5,7 +5,18 @@ RBT - ROBOT AGT - AGENT +[1.3.0] +- ПОРТИРОВАНО НА LINUX (Ubuntu, Debian, Astra), адаптация всех функций +- ОРКЕСТРАТОР +- - Manager.ControlPanel: Поддерживает установку пути по формата Linux и Windows +- Обновление дизайна в соответствии с порталом (шапка + подвал) +- СТУДИЯ +- Обновление дизайна в соответствии с порталом (шапка + подвал) +- ДОПОЛНИТЕЛЬНО +- - Jinja2: Создание класса быстрой инициализации pyopenRPA.Tools.Template + [1.2.13] +- ДОКУМЕНТАЦИЯ - переведена на русский язык - ORCHESTRATOR - - def WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: str = None, inHeadersDict: dict = None): - ROBOT