From 1ac3fd2a7439f7e0187c09bcdc8c791ea06039b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=20=D0=9C=D0=B0=D1=81=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Mon, 31 Oct 2022 12:24:16 +0300 Subject: [PATCH] Add & test pyOpenRPA.Utils.Disk>TemplateFile/Folder --- Sources/pyOpenRPA/Tools/CrossOS.py | 77 +------------ Sources/pyOpenRPA/Tools/Debugger.py | 25 +--- Sources/pyOpenRPA/Tools/License.py | 170 +--------------------------- Sources/pyOpenRPA/Tools/StopSafe.py | 67 +---------- Sources/pyOpenRPA/Utils/CrossOS.py | 76 +++++++++++++ Sources/pyOpenRPA/Utils/Debugger.py | 24 ++++ Sources/pyOpenRPA/Utils/Disk.py | 38 ++++++- Sources/pyOpenRPA/Utils/License.py | 169 +++++++++++++++++++++++++++ Sources/pyOpenRPA/Utils/StopSafe.py | 66 +++++++++++ changelog.md | 2 + 10 files changed, 374 insertions(+), 340 deletions(-) create mode 100644 Sources/pyOpenRPA/Utils/CrossOS.py create mode 100644 Sources/pyOpenRPA/Utils/Debugger.py create mode 100644 Sources/pyOpenRPA/Utils/License.py create mode 100644 Sources/pyOpenRPA/Utils/StopSafe.py diff --git a/Sources/pyOpenRPA/Tools/CrossOS.py b/Sources/pyOpenRPA/Tools/CrossOS.py index 90f57be2..af3fe01d 100755 --- a/Sources/pyOpenRPA/Tools/CrossOS.py +++ b/Sources/pyOpenRPA/Tools/CrossOS.py @@ -1,76 +1 @@ -import platform -""" -Специфические команды, которые надо выполнять только на ОС семейства Linux: if OS.IS_LINUX_BOOL: - -Специфические команды, которые надо выполнять только на ОС семейства Windows: if OS.IS_WINDOWS_BOOL: - -""" -IS_LINUX_BOOL = (platform.system().upper()=="LINUX" or platform.system().upper()=="LINUX2") -IS_WINDOWS_BOOL = (platform.system()=="Windows") - -def PathStr(inPathStr:str) -> str: - """Преобразование строк, который содержат путь к каталогу или файлу. В зависимости от операционной системы поддерживаются разные форматы. - - Для Windows ОС: path\\to\\file - Для Linux ОС: path/to/file - - .. code-block:: python - - from pyOpenRPA.Tools import CrossOS - lPathStr = CrossOS.PathStr(inPathStr = 'path/to\\file') - # WINDOWS: lPathStr == 'path\\to\\file' - # LINUX: lPathStr == 'path/to/file' - - :param inPathStr: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение - :type inPathStr: str - :return: Обработанная строка с учетом используемой ОС - :rtype: str - """ - if inPathStr is None: return None - if IS_WINDOWS_BOOL: - return inPathStr.replace("/","\\") - if IS_LINUX_BOOL: - 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("/") - - -def PathJoinList(inList: list) ->str: - """Слияние элементов списка в строку. Учитывает специфику формирования путей в разных ОС (Windows, Linux) - - Для Windows ОС: path\\to\\file - Для Linux ОС: path/to/file - - .. code-block:: python - - from pyOpenRPA.Tools import CrossOS - lPathStr = CrossOS.PathJoinList(inList = ['path', 'to', 'file'] ) - # WINDOWS: lPathStr == 'path\\to\\file' - # LINUX: lPathStr == 'path/to/file' - - :param inList: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение - :type inList: str - :return: Массив элементов пути. Пример: ['path', 'to', 'file'] - :rtype: list - """ - if IS_LINUX_BOOL: return "/".join(inList) - elif IS_WINDOWS_BOOL: return "\\".join(inList) \ No newline at end of file +from ..Utils.CrossOS import * \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/Debugger.py b/Sources/pyOpenRPA/Tools/Debugger.py index 69bbb55f..c05dba7b 100755 --- a/Sources/pyOpenRPA/Tools/Debugger.py +++ b/Sources/pyOpenRPA/Tools/Debugger.py @@ -1,24 +1 @@ -import os -import threading -import pdb -import time - -"""Module wait file "init_debug" in working directory -""" - -gKWARGS = None - -def LiveDebugCheckLoop(): - while True: - if os.path.exists("init_debug"): - pdb.set_trace() - time.sleep(30.0) - -def LiveDebugCheckThread(**inKWARGS): - """Create thread to wait file appear "init_debug" in the working directory. - """ - global gKWARGS - gKWARGS = inKWARGS - lThread = threading.Thread(target=LiveDebugCheckLoop) - lThread.setName("DEBUG_LIVE") - lThread.start() \ No newline at end of file +from ..Utils.Debugger import * \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/License.py b/Sources/pyOpenRPA/Tools/License.py index a69d135a..2a6104d2 100755 --- a/Sources/pyOpenRPA/Tools/License.py +++ b/Sources/pyOpenRPA/Tools/License.py @@ -1,169 +1 @@ -""" -pyOpenRPA open license -pyOpenRPA открытая лицензия - -Copyright (c) 2019 Ivan Maslov -Правообладатель: 2019 Маслов Иван Дмитриевич - -Текст лицензии см. в файле: LICENSE.PDF (в корне репозитория) или по адресу: https://pyopenrpa.ru/license/oferta.pdf - -https://stackoverflow.com/questions/40574732/windows-data-storage-for-all-users - -certificate.key - -""" -import os -import sys -import time -from pyOpenRPA.Tools import CrossOS -if CrossOS.IS_WINDOWS_BOOL: gProgramDataPathStr = "C:\\ProgramData" -if CrossOS.IS_LINUX_BOOL: gProgramDataPathStr = os.path.expanduser("~/.config") - -gProgramDataPORPathStr = os.path.join(gProgramDataPathStr, "pyOpenRPA") -gProgramDataCertificateFilePathStr = os.path.join(gProgramDataPORPathStr, "certificate.key") - -# TODO Изменить права, чтобы другие пользователи могли править - -if not os.path.exists(gProgramDataPORPathStr): os.mkdir(gProgramDataPORPathStr) - -def CertificateExists() -> bool: - """Check if the certificate key has been inserted - - :return: True - certificate key has been inserted; False - not has been inserted - :rtype: bool - """ - return os.path.exists(gProgramDataCertificateFilePathStr) - -def CertificateKeySet(inCertificateKeyStr: str): - """Get the certificate key string - - :param inCertificateKeyStr: Certificate key string (see license.pdf) - :type inCertificateKeyStr: str - """ - lFile = open(gProgramDataCertificateFilePathStr, "w", encoding="utf8") - lFile.write(inCertificateKeyStr) - lFile.close() - -def CertificateKeyGet() -> str or None: - """Get the certificate key from file - - :return: Certificate key (see license.pdf) - :rtype: str or None (if key is not set) - """ - - lCertificateKeyStr=None - if CertificateExists(): - lFile = open(gProgramDataCertificateFilePathStr, "r", encoding="utf8") - lCertificateKeyStr = lFile.read() - lFile.close() - return lCertificateKeyStr - -def ConsoleVerify() -> bool: - """ Write info about certificate which has been detected on the machine - - :return: true - certificate exists - :rtype: bool - """ - lCertificateExistsBool = False - if "PYOPENRPA_NODISP" not in os.environ: - lCertificateExistsBool = True - - - lCertificateKeyStr = CertificateKeyGet() - if lCertificateKeyStr is None: - lTextStr = """ -Цифровой сертификат pyOpenRPA не обнаружен. - -Получить или проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: -https://pyopenrpa.ru/verification -Операция формирования сертификата является автоматизированной и занимает несколько секунд. - -pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. -По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: -https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf -Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. - -ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. - """ - - print(lTextStr) - os.environ["PYOPENRPA_NODISP"]="1" - lCertificateExistsBool = False - time.sleep(5) - ConsoleAccept() - else: - lTextStr = """ -Обнаружен цифровой сертификат pyOpenRPA: {0}. - -Проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: -https://pyopenrpa.ru/verification - -pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. -По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: -https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf -Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. - -ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. - """.format(lCertificateKeyStr) - print(lTextStr) - os.environ["PYOPENRPA_NODISP"]="1" - return lCertificateExistsBool - -def ConsoleAccept(): - """ Start pyOpenRPA activation master - - :return: _description_ - :rtype: str - """ - if "PYOPENRPA_NODISP" not in os.environ: - lText=""" -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░ -░░░░░░░░░░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░ -░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░░ -░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░░ -░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░ ░░░ -░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░ ░░░░░ -░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ -░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░ -░░░░░ ░░ ░░░░░ ░░ ░░░░░░░░░░░░░░ -░░░░░░░ ░░░░░ ░░░░░░░░░░░░░░░░ -░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░ ░░░ ░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░ ░░░░░░░░░░ -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ - """ - print(lText) - time.sleep(2) - lText=""" -(RUS LANGUAGE) -*********************************************** -Добро пожаловать в систему активации pyOpenRPA! -*********************************************** - -pyOpenRPA - это открытое программное обеспечение класса RPA, которое разработано и зарегистрировано на территории Российской Федерации (Автор Иван Маслов, 2019г.). Все исходные коды доступны неограниченному кругу лиц для просмотра. -Данное ПО позволяет решить любые задачи, относящиеся к классу программной роботизации RPA. - -Перед использованием просим убедиться в том, что Вы обладаете действующим цифровым сертификатом pyOpenRPA (далее сертификат). -Данный сертификат является свидетельством того, что Вы наделены правами в отношении pyOpenRPA в соответствии с законодательством Российской Федерации. - -Получить или проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: -https://pyopenrpa.ru/verification -Операция формирования сертификата является автоматизированной и занимает несколько секунд. - -pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. -По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: -https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf -Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. - -ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. - """ - #print(os.get_terminal_size()) - print(lText) - os.environ["PYOPENRPA_NODISP"]="1" - lCertificateKeyStr = input("Укажите код сертификата:") - CertificateKeySet(inCertificateKeyStr=lCertificateKeyStr) \ No newline at end of file +from ..Utils.License import * \ No newline at end of file diff --git a/Sources/pyOpenRPA/Tools/StopSafe.py b/Sources/pyOpenRPA/Tools/StopSafe.py index d7ba3d2c..a1a24e77 100755 --- a/Sources/pyOpenRPA/Tools/StopSafe.py +++ b/Sources/pyOpenRPA/Tools/StopSafe.py @@ -1,66 +1 @@ -""" -# How to use -# from pyOpenRPA.Tools import StopSafe -# StopSafe.Init(inLogger=None) -# StopSafe.IsSafeStop() # True - WM_CLOSE SIGNAL has come. taskkill /im someprocess.exe -""" - - -import win32con -import win32gui -import os -gIsSignalCloseBool = False -gLogger = None -gWindowTitleStr = "PythonTerminator" # Title of the phantom window -gWindowDescriptionStr = "pyOpenRPA library for safe turn off the program (by send the WM_CLOSE signal from task kill)" # Description of the phantom window - -def Init(inLogger=None): - """ - Init the StopSafe module. After that you can use def IsStopSafe() to check if close signal has come. - - :param inLogger: Logger to log messages about StopSafe - :return: - """ - global gLogger - global gIsSignalCloseBool - gIsSignalCloseBool = False # Init default - gLogger = inLogger - import threading - if gLogger: gLogger.info(f"Безопасная остановка: получен сигнал безопасной остановки") - shutdown_thread = threading.Thread(target=_shutdown_monitor) - shutdown_thread.start() - #shutdown_thread.join() - #shutdown_monitor() - - -def IsStopSafe(): - """ - Check if stop signal has come. - - :return: - """ - global gIsSignalCloseBool # Init the global variable - return gIsSignalCloseBool # Return the result - -def _shutdown_monitor(): - global gIsSignalCloseBool # Init the global variable - global gLogger - def wndproc(hwnd, msg, wparam, lparam): - if msg == win32con.WM_CLOSE: - win32gui.DestroyWindow(hwnd) - return 0 - elif msg == win32con.WM_DESTROY: - win32gui.PostQuitMessage(0) - return 0 - return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) - wc = win32gui.WNDCLASS() - wc.lpszClassName = gWindowTitleStr - wc.lpfnWndProc = wndproc - win32gui.RegisterClass(wc) - hwnd = win32gui.CreateWindow(gWindowTitleStr, gWindowDescriptionStr, - 0, 0, 0, 0, 0, 0, 0, 0, None) - win32gui.PumpMessages() - gIsSignalCloseBool = True # WM_CLOSE message has come - if gLogger: - gLogger.info(f"Безопасная остановка: Получен сигнал безопасной остановки (VM_CLOSE) - выполнить остановку") - +from ..Utils.StopSafe import * \ No newline at end of file diff --git a/Sources/pyOpenRPA/Utils/CrossOS.py b/Sources/pyOpenRPA/Utils/CrossOS.py new file mode 100644 index 00000000..90f57be2 --- /dev/null +++ b/Sources/pyOpenRPA/Utils/CrossOS.py @@ -0,0 +1,76 @@ +import platform +""" +Специфические команды, которые надо выполнять только на ОС семейства Linux: if OS.IS_LINUX_BOOL: + +Специфические команды, которые надо выполнять только на ОС семейства Windows: if OS.IS_WINDOWS_BOOL: + +""" +IS_LINUX_BOOL = (platform.system().upper()=="LINUX" or platform.system().upper()=="LINUX2") +IS_WINDOWS_BOOL = (platform.system()=="Windows") + +def PathStr(inPathStr:str) -> str: + """Преобразование строк, который содержат путь к каталогу или файлу. В зависимости от операционной системы поддерживаются разные форматы. + + Для Windows ОС: path\\to\\file + Для Linux ОС: path/to/file + + .. code-block:: python + + from pyOpenRPA.Tools import CrossOS + lPathStr = CrossOS.PathStr(inPathStr = 'path/to\\file') + # WINDOWS: lPathStr == 'path\\to\\file' + # LINUX: lPathStr == 'path/to/file' + + :param inPathStr: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение + :type inPathStr: str + :return: Обработанная строка с учетом используемой ОС + :rtype: str + """ + if inPathStr is None: return None + if IS_WINDOWS_BOOL: + return inPathStr.replace("/","\\") + if IS_LINUX_BOOL: + 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("/") + + +def PathJoinList(inList: list) ->str: + """Слияние элементов списка в строку. Учитывает специфику формирования путей в разных ОС (Windows, Linux) + + Для Windows ОС: path\\to\\file + Для Linux ОС: path/to/file + + .. code-block:: python + + from pyOpenRPA.Tools import CrossOS + lPathStr = CrossOS.PathJoinList(inList = ['path', 'to', 'file'] ) + # WINDOWS: lPathStr == 'path\\to\\file' + # LINUX: lPathStr == 'path/to/file' + + :param inList: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение + :type inList: str + :return: Массив элементов пути. Пример: ['path', 'to', 'file'] + :rtype: list + """ + if IS_LINUX_BOOL: return "/".join(inList) + elif IS_WINDOWS_BOOL: return "\\".join(inList) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Utils/Debugger.py b/Sources/pyOpenRPA/Utils/Debugger.py new file mode 100644 index 00000000..69bbb55f --- /dev/null +++ b/Sources/pyOpenRPA/Utils/Debugger.py @@ -0,0 +1,24 @@ +import os +import threading +import pdb +import time + +"""Module wait file "init_debug" in working directory +""" + +gKWARGS = None + +def LiveDebugCheckLoop(): + while True: + if os.path.exists("init_debug"): + pdb.set_trace() + time.sleep(30.0) + +def LiveDebugCheckThread(**inKWARGS): + """Create thread to wait file appear "init_debug" in the working directory. + """ + global gKWARGS + gKWARGS = inKWARGS + lThread = threading.Thread(target=LiveDebugCheckLoop) + lThread.setName("DEBUG_LIVE") + lThread.start() \ No newline at end of file diff --git a/Sources/pyOpenRPA/Utils/Disk.py b/Sources/pyOpenRPA/Utils/Disk.py index a405ceb7..fb2ece05 100644 --- a/Sources/pyOpenRPA/Utils/Disk.py +++ b/Sources/pyOpenRPA/Utils/Disk.py @@ -1,11 +1,39 @@ +from email import utils import os import shutil +from . import CrossOS -def CheckFile(inDstPathStr, inTmplPathStr): - if os.path.exists(inDstPathStr) == False: - shutil.copy(inTmplPathStr, inDstPathStr) +def TemplateFolder(inDstPathStr): + """L+,W+: Сформировать папку (набор папок), если ранее эти папки не существовали -def CheckFolder(inDstPathStr): + .. code-block:: python + + from pyOpenRPA.Utils import Disk + Disk.TemplateFolder(inDstPathStr="path\\to\\folder") + + :param inDstPathStr: Путь к папке, которая должна существовать + :type inDstPathStr: str + """ # проверка наличия всех файлов/каталогов if not os.path.exists(os.path.abspath(inDstPathStr)): - os.mkdir(inDstPathStr) \ No newline at end of file + os.makedirs(inDstPathStr, exist_ok=True) + +def TemplateFile(inDstPathStr, inTmplPathStr): + """L+,W+: Сформировать файл (копировать из шаблона), если ранее этот файл не существовал + + .. code-block:: python + + from pyOpenRPA.Utils import Disk + Disk.TemplateFile(inDstPathStr="path\\to\\destination\\file.txt", inTmplPathStr="path\\to\\template.txt") + + :param inDstPathStr: Путь к файлу, который должен существовать. Если не существует - скопировать из шаблона inTmplPathStr + :type inDstPathStr: str + :param inTmplPathStr: Путь к файлу шаблона, который потребуется копировать, если файл inDstPathStr не будет обнаружен + :type inTmplPathStr: str + """ + TemplateFolder(inDstPathStr=CrossOS.PathJoinList(inList=CrossOS.PathSplitList(inPathStr=inDstPathStr)[:-1])) + if os.path.exists(inDstPathStr) == False: + shutil.copy(inTmplPathStr, inDstPathStr) + +CheckFolder = TemplateFolder +CheckFile = TemplateFile \ No newline at end of file diff --git a/Sources/pyOpenRPA/Utils/License.py b/Sources/pyOpenRPA/Utils/License.py new file mode 100644 index 00000000..a69d135a --- /dev/null +++ b/Sources/pyOpenRPA/Utils/License.py @@ -0,0 +1,169 @@ +""" +pyOpenRPA open license +pyOpenRPA открытая лицензия + +Copyright (c) 2019 Ivan Maslov +Правообладатель: 2019 Маслов Иван Дмитриевич + +Текст лицензии см. в файле: LICENSE.PDF (в корне репозитория) или по адресу: https://pyopenrpa.ru/license/oferta.pdf + +https://stackoverflow.com/questions/40574732/windows-data-storage-for-all-users + +certificate.key + +""" +import os +import sys +import time +from pyOpenRPA.Tools import CrossOS +if CrossOS.IS_WINDOWS_BOOL: gProgramDataPathStr = "C:\\ProgramData" +if CrossOS.IS_LINUX_BOOL: gProgramDataPathStr = os.path.expanduser("~/.config") + +gProgramDataPORPathStr = os.path.join(gProgramDataPathStr, "pyOpenRPA") +gProgramDataCertificateFilePathStr = os.path.join(gProgramDataPORPathStr, "certificate.key") + +# TODO Изменить права, чтобы другие пользователи могли править + +if not os.path.exists(gProgramDataPORPathStr): os.mkdir(gProgramDataPORPathStr) + +def CertificateExists() -> bool: + """Check if the certificate key has been inserted + + :return: True - certificate key has been inserted; False - not has been inserted + :rtype: bool + """ + return os.path.exists(gProgramDataCertificateFilePathStr) + +def CertificateKeySet(inCertificateKeyStr: str): + """Get the certificate key string + + :param inCertificateKeyStr: Certificate key string (see license.pdf) + :type inCertificateKeyStr: str + """ + lFile = open(gProgramDataCertificateFilePathStr, "w", encoding="utf8") + lFile.write(inCertificateKeyStr) + lFile.close() + +def CertificateKeyGet() -> str or None: + """Get the certificate key from file + + :return: Certificate key (see license.pdf) + :rtype: str or None (if key is not set) + """ + + lCertificateKeyStr=None + if CertificateExists(): + lFile = open(gProgramDataCertificateFilePathStr, "r", encoding="utf8") + lCertificateKeyStr = lFile.read() + lFile.close() + return lCertificateKeyStr + +def ConsoleVerify() -> bool: + """ Write info about certificate which has been detected on the machine + + :return: true - certificate exists + :rtype: bool + """ + lCertificateExistsBool = False + if "PYOPENRPA_NODISP" not in os.environ: + lCertificateExistsBool = True + + + lCertificateKeyStr = CertificateKeyGet() + if lCertificateKeyStr is None: + lTextStr = """ +Цифровой сертификат pyOpenRPA не обнаружен. + +Получить или проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: +https://pyopenrpa.ru/verification +Операция формирования сертификата является автоматизированной и занимает несколько секунд. + +pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. +По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: +https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf +Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. + +ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. + """ + + print(lTextStr) + os.environ["PYOPENRPA_NODISP"]="1" + lCertificateExistsBool = False + time.sleep(5) + ConsoleAccept() + else: + lTextStr = """ +Обнаружен цифровой сертификат pyOpenRPA: {0}. + +Проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: +https://pyopenrpa.ru/verification + +pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. +По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: +https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf +Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. + +ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. + """.format(lCertificateKeyStr) + print(lTextStr) + os.environ["PYOPENRPA_NODISP"]="1" + return lCertificateExistsBool + +def ConsoleAccept(): + """ Start pyOpenRPA activation master + + :return: _description_ + :rtype: str + """ + if "PYOPENRPA_NODISP" not in os.environ: + lText=""" +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░ +░░░░░░░░░░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░ +░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░░ +░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░░ +░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░ ░░░ +░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░ ░░░░░ +░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ +░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░░ +░░░░░ ░░ ░░░░░ ░░ ░░░░░░░░░░░░░░ +░░░░░░░ ░░░░░ ░░░░░░░░░░░░░░░░ +░░░░░░░░░░ ░░░░░ ░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░ ░░░ ░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░ ░░░░░░░░░░ +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ +░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ + """ + print(lText) + time.sleep(2) + lText=""" +(RUS LANGUAGE) +*********************************************** +Добро пожаловать в систему активации pyOpenRPA! +*********************************************** + +pyOpenRPA - это открытое программное обеспечение класса RPA, которое разработано и зарегистрировано на территории Российской Федерации (Автор Иван Маслов, 2019г.). Все исходные коды доступны неограниченному кругу лиц для просмотра. +Данное ПО позволяет решить любые задачи, относящиеся к классу программной роботизации RPA. + +Перед использованием просим убедиться в том, что Вы обладаете действующим цифровым сертификатом pyOpenRPA (далее сертификат). +Данный сертификат является свидетельством того, что Вы наделены правами в отношении pyOpenRPA в соответствии с законодательством Российской Федерации. + +Получить или проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: +https://pyopenrpa.ru/verification +Операция формирования сертификата является автоматизированной и занимает несколько секунд. + +pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. +По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: +https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf +Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. + +ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ. + """ + #print(os.get_terminal_size()) + print(lText) + os.environ["PYOPENRPA_NODISP"]="1" + lCertificateKeyStr = input("Укажите код сертификата:") + CertificateKeySet(inCertificateKeyStr=lCertificateKeyStr) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Utils/StopSafe.py b/Sources/pyOpenRPA/Utils/StopSafe.py new file mode 100644 index 00000000..d7ba3d2c --- /dev/null +++ b/Sources/pyOpenRPA/Utils/StopSafe.py @@ -0,0 +1,66 @@ +""" +# How to use +# from pyOpenRPA.Tools import StopSafe +# StopSafe.Init(inLogger=None) +# StopSafe.IsSafeStop() # True - WM_CLOSE SIGNAL has come. taskkill /im someprocess.exe +""" + + +import win32con +import win32gui +import os +gIsSignalCloseBool = False +gLogger = None +gWindowTitleStr = "PythonTerminator" # Title of the phantom window +gWindowDescriptionStr = "pyOpenRPA library for safe turn off the program (by send the WM_CLOSE signal from task kill)" # Description of the phantom window + +def Init(inLogger=None): + """ + Init the StopSafe module. After that you can use def IsStopSafe() to check if close signal has come. + + :param inLogger: Logger to log messages about StopSafe + :return: + """ + global gLogger + global gIsSignalCloseBool + gIsSignalCloseBool = False # Init default + gLogger = inLogger + import threading + if gLogger: gLogger.info(f"Безопасная остановка: получен сигнал безопасной остановки") + shutdown_thread = threading.Thread(target=_shutdown_monitor) + shutdown_thread.start() + #shutdown_thread.join() + #shutdown_monitor() + + +def IsStopSafe(): + """ + Check if stop signal has come. + + :return: + """ + global gIsSignalCloseBool # Init the global variable + return gIsSignalCloseBool # Return the result + +def _shutdown_monitor(): + global gIsSignalCloseBool # Init the global variable + global gLogger + def wndproc(hwnd, msg, wparam, lparam): + if msg == win32con.WM_CLOSE: + win32gui.DestroyWindow(hwnd) + return 0 + elif msg == win32con.WM_DESTROY: + win32gui.PostQuitMessage(0) + return 0 + return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) + wc = win32gui.WNDCLASS() + wc.lpszClassName = gWindowTitleStr + wc.lpfnWndProc = wndproc + win32gui.RegisterClass(wc) + hwnd = win32gui.CreateWindow(gWindowTitleStr, gWindowDescriptionStr, + 0, 0, 0, 0, 0, 0, 0, 0, None) + win32gui.PumpMessages() + gIsSignalCloseBool = True # WM_CLOSE message has come + if gLogger: + gLogger.info(f"Безопасная остановка: Получен сигнал безопасной остановки (VM_CLOSE) - выполнить остановку") + diff --git a/changelog.md b/changelog.md index 1598ca25..5c6b654a 100755 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ RBT - ROBOT AGT - AGENT [1.3.2] +- ОБЩЕЕ +- - Utils: Disk - подготовка файлов / папок, если они не обнаружены (полезно при первом запуске, если требуются БД/ Файлы хранилищ) - ОРКЕСТРАТОР - - Поддержка многотысячной аудитории, одновременно работающей в панели управления (async server-data server-log with fastapi) - - Новые функции для упрощенной работы с FastAPI: Orchestrator.WebAuthDefGet Orchestrator.WebAppGet