diff --git a/Sources/pyOpenRPA/Robot/UIDesktop.py b/Sources/pyOpenRPA/Robot/UIDesktop.py
index 73142128..dcaa70b6 100755
--- a/Sources/pyOpenRPA/Robot/UIDesktop.py
+++ b/Sources/pyOpenRPA/Robot/UIDesktop.py
@@ -120,7 +120,7 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
:type inSpecificationList: list, обязательный
:param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии
:type inElement: UIO объект, опциональный
- :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:return: Список UIO объектов, которые удовлетворяют условиям UIO селектора
'''
@@ -128,123 +128,127 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
inSpecificationList=copy.deepcopy(inSpecificationList)
lResultList=[]
lChildrenList=[]
- #Получить родительский объект если на вход ничего не поступило
- if inElement is None:
- #сформировать спецификацию на получение элемента
- lRootElementSpecification=[inSpecificationList[0]]
- lRootElementList=PWASpecification_Get_UIO(lRootElementSpecification)
- for lRootItem in lRootElementList:
- if lRootItem is not None:
- lChildrenList.append(lRootItem.wrapper_object())
- #Елемент на вход поступил - выполнить его анализ
- else:
- #Получить список элементов
- lElementChildrenList=inElement.children()
- #Поступил index - точное добавление
- if 'index' in inSpecificationList[0]:
- if inSpecificationList[0]['index']1:
+ lFlagGoCheck=False
+ #Циклический обход по детям, на предмет соответствия всем условиям
+ for lChildrenItem in lElementChildrenList:
+ #Обработка глубины depth (рекурсивный вызов для всех детей с занижением индекса глубины)
+ #По умолчанию значение глубины 1
+ if 'depth_end' in inSpecificationList[0]:
+ if inSpecificationList[0]['depth_end']>1:
+ #Подготовка новой версии спецификации
+ lChildrenItemNewSpecificationList=inSpecificationList.copy()
+ lChildrenItemNewSpecificationList[0]=lChildrenItemNewSpecificationList[0].copy()
+ lChildrenItemNewSpecificationList[0]["depth_end"]=lChildrenItemNewSpecificationList[0]["depth_end"]-1
+ if 'depth_start' in lChildrenItemNewSpecificationList[0]:
+ lChildrenItemNewSpecificationList[0]["depth_start"]=lChildrenItemNewSpecificationList[0]["depth_start"]-1
+ #Циклический вызов для всех детей со скорректированной спецификацией
+ lResultList.extend(UIOSelector_Get_UIOList(lChildrenItemNewSpecificationList,lChildrenItem,inFlagRaiseException))
+ #Фильтрация
+ #TODO Сделать поддержку этих атрибутов для первого уровня селектора
+ if lFlagGoCheck:
+ lFlagAddChild=True
+ #Фильтрация по title
+ if 'title' in inSpecificationList[0]:
+ if lChildrenItem.element_info.name != inSpecificationList[0]["title"]:
+ lFlagAddChild=False
+ #Фильтрация по title_re (regexp)
+ if 'title_re' in inSpecificationList[0]:
+ if re.fullmatch(inSpecificationList[0]["title_re"],lChildrenItem.element_info.name) is None:
+ lFlagAddChild=False
+ #Фильтрация по rich_text
+ if 'rich_text' in inSpecificationList[0]:
+ if lChildrenItem.element_info.rich_text != inSpecificationList[0]["rich_text"]:
+ lFlagAddChild=False
+ #Фильтрация по rich_text_re (regexp)
+ if 'rich_text_re' in inSpecificationList[0]:
+ if re.fullmatch(inSpecificationList[0]["rich_text_re"],lChildrenItem.element_info.rich_text) is None:
+ lFlagAddChild=False
+ #Фильтрация по class_name
+ if 'class_name' in inSpecificationList[0]:
+ if lChildrenItem.element_info.class_name != inSpecificationList[0]["class_name"]:
+ lFlagAddChild=False
+ #Фильтрация по class_name_re (regexp)
+ if 'class_name_re' in inSpecificationList[0]:
+ if re.fullmatch(inSpecificationList[0]["class_name_re"],lChildrenItem.element_info.class_name) is None:
+ lFlagAddChild=False
+ #Фильтрация по friendly_class_name
+ if 'friendly_class_name' in inSpecificationList[0]:
+ if lChildrenItem.friendly_class_name() != inSpecificationList[0]["friendly_class_name"]:
+ lFlagAddChild=False
+ #Фильтрация по friendly_class_name_re (regexp)
+ if 'friendly_class_name_re' in inSpecificationList[0]:
+ if re.fullmatch(inSpecificationList[0]["friendly_class_name_re"],lChildrenItem.friendly_class_name) is None:
+ lFlagAddChild=False
+ #Фильтрация по control_type
+ if 'control_type' in inSpecificationList[0]:
+ if lChildrenItem.element_info.control_type != inSpecificationList[0]["control_type"]:
+ lFlagAddChild=False
+ #Фильтрация по control_type_re (regexp)
+ if 'control_type_re' in inSpecificationList[0]:
+ if re.fullmatch(inSpecificationList[0]["control_type_re"],lChildrenItem.element_info.control_type) is None:
+ lFlagAddChild=False
+ #Фильтрация по is_enabled (bool)
+ if 'is_enabled' in inSpecificationList[0]:
+ if lChildrenItem.is_enabled()!=inSpecificationList[0]["is_enabled"]:
+ lFlagAddChild=False
+ #Фильтрация по is_visible (bool)
+ if 'is_visible' in inSpecificationList[0]:
+ if lChildrenItem.is_visible()!=inSpecificationList[0]["is_visible"]:
+ lFlagAddChild=False
+ #####
+ #Все проверки пройдены - флаг добавления
+ if lFlagAddChild:
+ lChildrenList.append(lChildrenItem)
+ #Выполнить рекурсивный вызов (уменьшение количества спецификаций), если спецификация больше одного элемента
+ #????????Зачем в условии ниже is not None ???????????
+ if len(inSpecificationList)>1 and len(lChildrenList)>0:
+ #Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект
+ for lChildElement in lChildrenList:
+ lResultList.extend(UIOSelector_Get_UIOList(inSpecificationList[1:],lChildElement,inFlagRaiseException))
else:
- lFlagGoCheck=True
- #Учесть поле depth_start (если указано)
- if 'depth_start' in inSpecificationList[0]:
- if inSpecificationList[0]["depth_start"]>1:
- lFlagGoCheck=False
- #Циклический обход по детям, на предмет соответствия всем условиям
- for lChildrenItem in lElementChildrenList:
- #Обработка глубины depth (рекурсивный вызов для всех детей с занижением индекса глубины)
- #По умолчанию значение глубины 1
- if 'depth_end' in inSpecificationList[0]:
- if inSpecificationList[0]['depth_end']>1:
- #Подготовка новой версии спецификации
- lChildrenItemNewSpecificationList=inSpecificationList.copy()
- lChildrenItemNewSpecificationList[0]=lChildrenItemNewSpecificationList[0].copy()
- lChildrenItemNewSpecificationList[0]["depth_end"]=lChildrenItemNewSpecificationList[0]["depth_end"]-1
- if 'depth_start' in lChildrenItemNewSpecificationList[0]:
- lChildrenItemNewSpecificationList[0]["depth_start"]=lChildrenItemNewSpecificationList[0]["depth_start"]-1
- #Циклический вызов для всех детей со скорректированной спецификацией
- lResultList.extend(UIOSelector_Get_UIOList(lChildrenItemNewSpecificationList,lChildrenItem,inFlagRaiseException))
- #Фильтрация
- #TODO Сделать поддержку этих атрибутов для первого уровня селектора
- if lFlagGoCheck:
- lFlagAddChild=True
- #Фильтрация по title
- if 'title' in inSpecificationList[0]:
- if lChildrenItem.element_info.name != inSpecificationList[0]["title"]:
- lFlagAddChild=False
- #Фильтрация по title_re (regexp)
- if 'title_re' in inSpecificationList[0]:
- if re.fullmatch(inSpecificationList[0]["title_re"],lChildrenItem.element_info.name) is None:
- lFlagAddChild=False
- #Фильтрация по rich_text
- if 'rich_text' in inSpecificationList[0]:
- if lChildrenItem.element_info.rich_text != inSpecificationList[0]["rich_text"]:
- lFlagAddChild=False
- #Фильтрация по rich_text_re (regexp)
- if 'rich_text_re' in inSpecificationList[0]:
- if re.fullmatch(inSpecificationList[0]["rich_text_re"],lChildrenItem.element_info.rich_text) is None:
- lFlagAddChild=False
- #Фильтрация по class_name
- if 'class_name' in inSpecificationList[0]:
- if lChildrenItem.element_info.class_name != inSpecificationList[0]["class_name"]:
- lFlagAddChild=False
- #Фильтрация по class_name_re (regexp)
- if 'class_name_re' in inSpecificationList[0]:
- if re.fullmatch(inSpecificationList[0]["class_name_re"],lChildrenItem.element_info.class_name) is None:
- lFlagAddChild=False
- #Фильтрация по friendly_class_name
- if 'friendly_class_name' in inSpecificationList[0]:
- if lChildrenItem.friendly_class_name() != inSpecificationList[0]["friendly_class_name"]:
- lFlagAddChild=False
- #Фильтрация по friendly_class_name_re (regexp)
- if 'friendly_class_name_re' in inSpecificationList[0]:
- if re.fullmatch(inSpecificationList[0]["friendly_class_name_re"],lChildrenItem.friendly_class_name) is None:
- lFlagAddChild=False
- #Фильтрация по control_type
- if 'control_type' in inSpecificationList[0]:
- if lChildrenItem.element_info.control_type != inSpecificationList[0]["control_type"]:
- lFlagAddChild=False
- #Фильтрация по control_type_re (regexp)
- if 'control_type_re' in inSpecificationList[0]:
- if re.fullmatch(inSpecificationList[0]["control_type_re"],lChildrenItem.element_info.control_type) is None:
- lFlagAddChild=False
- #Фильтрация по is_enabled (bool)
- if 'is_enabled' in inSpecificationList[0]:
- if lChildrenItem.is_enabled()!=inSpecificationList[0]["is_enabled"]:
- lFlagAddChild=False
- #Фильтрация по is_visible (bool)
- if 'is_visible' in inSpecificationList[0]:
- if lChildrenItem.is_visible()!=inSpecificationList[0]["is_visible"]:
- lFlagAddChild=False
- #####
- #Все проверки пройдены - флаг добавления
- if lFlagAddChild:
- lChildrenList.append(lChildrenItem)
- #Выполнить рекурсивный вызов (уменьшение количества спецификаций), если спецификация больше одного элемента
- #????????Зачем в условии ниже is not None ???????????
- if len(inSpecificationList)>1 and len(lChildrenList)>0:
- #Вызвать рекурсивно функцию получения следующего объекта, если в спецификации есть следующий объект
- for lChildElement in lChildrenList:
- lResultList.extend(UIOSelector_Get_UIOList(inSpecificationList[1:],lChildElement,inFlagRaiseException))
- else:
- lResultList.extend(lChildrenList)
- #Условие, если результирующий список пустой и установлен флаг создания ошибки (и inElement is None - не следствие рекурсивного вызова)
- if inElement is None and len(lResultList)==0 and inFlagRaiseException:
- raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector")
- return lResultList
+ lResultList.extend(lChildrenList)
+ #Условие, если результирующий список пустой и установлен флаг создания ошибки (и inElement is None - не следствие рекурсивного вызова)
+ if inElement is None and len(lResultList)==0 and inFlagRaiseException:
+ raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector")
+ return lResultList
+ except Exception as e:
+ if inFlagRaiseException: raise e
+ else: return []
#old:PywinautoExtElementGet
def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException=True):
@@ -268,16 +272,13 @@ def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException
'''
lResult=None
#Получить родительский объект если на вход ничего не поступило
- lResultList=UIOSelector_Get_UIOList(inSpecificationList,inElement,False)
+ lResultList=UIOSelector_Get_UIOList(inSpecificationList,inElement,inFlagRaiseException)
if len(lResultList)>0:
lResult=lResultList[0]
- #Условие, если результирующий список пустой и установлен флаг создания ошибки (и inElement is None - не следствие рекурсивного вызова)
- if lResult is None and inFlagRaiseException:
- raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector")
return lResult
#old:-
-def UIOSelector_Exist_Bool (inUIOSelector):
+def UIOSelector_Exist_Bool (inUIOSelector, inFlagRaiseException=True):
'''L-,W+: Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -292,6 +293,8 @@ def UIOSelector_Exist_Bool (inUIOSelector):
:param inUIOSelector: UIO Селектор, который определяет критерии поиска UIO объектов
:type inUIOSelector: list, обязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:return: True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору
'''
lResult=False
@@ -299,7 +302,9 @@ def UIOSelector_Exist_Bool (inUIOSelector):
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить родительский объект если на вход ничего не поступило
- lResultList=UIOSelector_Get_UIOList(inUIOSelector, None, False)
+ try:
+ lResultList=UIOSelector_Get_UIOList(inUIOSelector, None, inFlagRaiseException)
+ except pywinauto.findwindows.ElementNotFoundError: return False
if len(lResultList)>0:
lResult=True
else:
@@ -319,7 +324,7 @@ def UIOSelector_Exist_Bool (inUIOSelector):
return lResult
#old: -
-def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False):
+def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False, inFlagRaiseException=True):
'''L-,W+: Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -342,6 +347,8 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
:type inSpecificationListList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области
:return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]
'''
@@ -356,7 +363,7 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
#Итерация проверки
lIndex = 0
for lItem in inSpecificationListList:
- lItemResultFlag=UIOSelector_Exist_Bool(lItem)
+ lItemResultFlag=UIOSelector_Exist_Bool(lItem, inFlagRaiseException=True)
#Если обнаружен элемент - добавить его индекс в массив
if lItemResultFlag:
lResultList.append(lIndex)
@@ -376,7 +383,7 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
return lResultList
#old: -
-def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False):
+def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False, inFlagRaiseException=True):
'''L-,W+: Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -399,6 +406,8 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
:type inSpecificationListList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области
:return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]
'''
@@ -414,7 +423,7 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
#Итерация проверки
lIndex = 0
for lItem in inSpecificationListList:
- lItemResultFlag=UIOSelector_Exist_Bool(lItem)
+ lItemResultFlag=UIOSelector_Exist_Bool(lItem,inFlagRaiseException=inFlagRaiseException)
#Если обнаружен элемент - добавить его индекс в массив
if not lItemResultFlag:
lResultList.append(lIndex)
@@ -434,7 +443,7 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
return lResultList
#old: -
-def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs):
+def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs, inFlagRaiseException=True):
'''L-,W+: Ожидать появление 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -451,16 +460,18 @@ def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs):
:type inSpecificationList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:return: True - UIO объект был обнаружен. False - обратная ситуациая
'''
- lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs)
+ lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs, inFlagRaiseException=inFlagRaiseException)
lResult=False
if len(lWaitAppearList)>0:
lResult=True
return lResult
#old name - -
-def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs):
+def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs,inFlagRaiseException=True):
'''L-,W+: Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -477,9 +488,11 @@ def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs):
:type inSpecificationList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:return: True - UIO объект был обнаружен. False - обратная ситуациая
'''
- lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs)
+ lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs,inFlagRaiseException=inFlagRaiseException)
lResult=False
if len(lWaitDisappearList)>0:
lResult=True
@@ -908,7 +921,7 @@ def UIO_GetCtrlIndex_Int(inElement):
return lResult
#old: - PywinautoExtElementsGetInfo
-def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None):
+def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None, inFlagRaiseException=True):
"""L-,W+: Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -925,13 +938,15 @@ def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None):
:type inUIOSelector: list, обязательный
:param inElement: UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений.
:type inElement: UIO объект, необязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:return: dict, пример: {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None}
"""
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить родительский объект если на вход ничего не поступило
- lResultList=UIOSelector_Get_UIOList(inUIOSelector, inElement)
+ lResultList=UIOSelector_Get_UIOList(inUIOSelector, inElement, inFlagRaiseException)
lIterator = 0
for lItem in lResultList:
lResultList[lIterator]=UIOEI_Convert_UIOInfo(lResultList[lIterator].element_info)
@@ -985,7 +1000,7 @@ def UIOSelector_TryRestore_Dict(inSpecificationList):
return lResult
#old: - ElementActionGetList
-def UIOSelector_Get_UIOActivityList (inUIOSelector):
+def UIOSelector_Get_UIOActivityList (inUIOSelector,inFlagRaiseException=True):
"""L-,W+: Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -1000,12 +1015,14 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector):
:param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.
:type inUIOSelector: list, обязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
"""
#Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None:
#Получить объект
- lObject=UIOSelector_Get_UIO(inUIOSelector)
+ lObject=UIOSelector_Get_UIO(inUIOSelector,inFlagRaiseException=inFlagRaiseException)
lActionList=dir(lObject)
lResult=dir(lObject)
#Выполнить чистку списка от неактуальных методов
@@ -1033,7 +1050,7 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector):
return lResult
#old: - ElementRunAction
-def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=None, inkwArgumentObject=None):
+def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inFlagRaiseException=True, inArgumentList=None, inkwArgumentObject=None):
"""L-,W+: Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector. Описание возможных активностей см. ниже.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@@ -1050,6 +1067,8 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=
:type inUIOSelector: list, обязательный
:param inActionName: наименование активности, которую требуется выполнить над UIO объектом
:type inActionName: str, обязательный
+ :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
+ :type inFlagRaiseException: bool, опциональный
:param inArgumentList: список передаваемых неименованных аргументов в функцию inActionName
:type inArgumentList: list, необязательный
:param inkwArgumentObject: словарь передаваемых именованных аргументов в функцию inActionName
@@ -1064,7 +1083,7 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=
#Run activity if SafeOtherProcess is None
if lSafeOtherProcess is None:
#Определить объект
- lObject=UIOSelector_Get_UIO(inUIOSelector)
+ lObject=UIOSelector_Get_UIO(inUIOSelector,inFlagRaiseException=inFlagRaiseException)
#Получить метод для вызова
lFunction = getattr(lObject, inActionName)
#Выполнить действие
diff --git a/Sources/pyOpenRPA/Robot/UIWeb.py b/Sources/pyOpenRPA/Robot/UIWeb.py
index 32d34f6d..5b493d9a 100755
--- a/Sources/pyOpenRPA/Robot/UIWeb.py
+++ b/Sources/pyOpenRPA/Robot/UIWeb.py
@@ -1,8 +1,10 @@
from selenium import *
from selenium import webdriver, common
from selenium.webdriver.common.by import By
+from selenium.common.exceptions import JavascriptException
import os
import sys
+import json
from pyOpenRPA.Tools import CrossOS
import time
@@ -14,8 +16,8 @@ UIO_WAIT_INTERVAL_SEC_FLOAT = 1.0
gBrowser:webdriver.Chrome = None
-def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = None, inExtensionPathList:list = None, inProfilePathStr:str=None) -> webdriver.Chrome:
- """L+,W+: Выполнить запуск браузера Chrome. Если вы скачали pyOpenRPA вместе с репозиторием, то будет использоваться встроенный браузер Google Chrome. Если установка pyOpenRPA производилась другим способом, то требуется указать расположение браузера Google Chrome и соответствующего WebDriver.
+def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = None, inExtensionPathList:list = None, inProfilePathStr:str=None, inSaveAsPDFBool = False, inSavefileDefaultDirStr = None) -> webdriver.Chrome:
+ """L+,W+: Выполнить запуск браузера Chrome. Если вы скачали pyOpenRPA вместе с репозиторием, то будет использоваться встроенный браузер Google Chrome. Если установка pyOpenRPA производилась другим способом, то требуется указать расположение браузера Google Chrome и соответствующего WebDriver
.. code-block:: python
@@ -32,6 +34,10 @@ def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = N
:type inExtensionPathList: list, опционально
:param inProfilePathStr: Путь, по которому выполнить сохранения профиля Chrome (история, куки и т.д.), по умолчанию None (профиль не сохраняется)
:type inProfilePathStr: str, опционально
+ :param inSaveAsPDFBool: Флаг, который обеспечивает настройки окна печати вэб-страницы как "Сохранить как PDF", по умолчанию False (настройки по умолчанию)
+ :type inSaveAsPDFBool: bool, опционально
+ :param inSavefileDefaultDirStr: Путь, по которому выполнить сохранения файла (после работы с окном печать вэб-страницы браузера) (история, куки и т.д.), по умолчанию None (файл не сохраняется)
+ :type inSavefileDefaultDirStr: str, опционально
:return: Объект браузера Google Chrome
:rtype: webdriver.Chrome
"""
@@ -54,8 +60,31 @@ def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = N
if CrossOS.IS_WINDOWS_BOOL: inChromeExePathStr = os.path.join(lResourcePathStr, "WChrome64-840414730", "App", "Chrome-bin", "chrome.exe")
elif CrossOS.IS_LINUX_BOOL: inChromeExePathStr = os.path.join(lResourcePathStr, "LChrome64-10305060114", "data", "chrome")
if inExtensionPathList == None: inExtensionPathList = []
- # Set full path to exe of the chrome
+ # Установка настроек окна печати, если необходимо
lWebDriverChromeOptionsInstance = webdriver.ChromeOptions()
+ if inSaveAsPDFBool == True and inSavefileDefaultDirStr is not None:
+ print_settings = {
+ "recentDestinations": [{
+ "id": "Save as PDF",
+ "origin": "local",
+ "account": "",
+ }],
+ "selectedDestinationId": "Save as PDF",
+ "version": 2, # в chrome - это номер варинта "сохранить как PDF"
+ "isHeaderFooterEnabled": False, # хедеры HTML на странице
+ "isLandscapeEnabled": False # ориентация (True - альбомная)
+ }
+ prefs = {'printing.print_preview_sticky_settings.appState': json.dumps(print_settings),
+ "download.prompt_for_download": False,
+ "profile.default_content_setting_values.automatic_downloads": 1,
+ "download.default_directory": inSavefileDefaultDirStr,
+ "savefile.default_directory": inSavefileDefaultDirStr,
+ "download.directory_upgrade": True,
+ "safebrowsing.enabled": True}
+
+ lWebDriverChromeOptionsInstance.add_experimental_option('prefs', prefs)
+ lWebDriverChromeOptionsInstance.add_argument('--kiosk-printing')
+ # Set full path to exe of the chrome
lWebDriverChromeOptionsInstance.binary_location = inChromeExePathStr
#lWebDriverChromeOptionsInstance2 = webdriver.ChromeOptions()
if inProfilePathStr is not None:
@@ -94,6 +123,8 @@ def BrowserChange(inBrowser):
def PageOpen(inURLStr: str):
"""L+,W+: Открыть страницу inURLStr в браузере и дождаться ее загрузки.
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
+
.. code-block:: python
# UIWeb: Взаимодействие с ui web
@@ -107,9 +138,30 @@ def PageOpen(inURLStr: str):
"""
global gBrowser
if gBrowser is not None: gBrowser.get(inURLStr)
+
+def PagePrint():
+ """L+,W+: Открыть окно печати браузера.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
+
+ .. code-block:: python
+
+ # UIWeb: Взаимодействие с ui web
+ from pyOpenRPA.Robot import UIWeb
+ import time
+ UIWeb.BrowserChromeStart()
+ UIWeb.PageOpen("https://mail.ru")
+ time.sleep(1)
+ UIWeb.PagePrint()
+ UIWeb.BrowserClose()
+
+ """
+ PageJSExecute(inJSStr=f"window.print()")
def PageScrollTo(inVerticalPxInt=0, inHorizontalPxInt=0):
"""L+,W+: Выполнить прокрутку страницы (по вертикали или по горизонтали)
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -129,6 +181,8 @@ def PageScrollTo(inVerticalPxInt=0, inHorizontalPxInt=0):
def PageJSExecute(inJSStr, *inArgList):
"""L+,W+: Отправить на выполнение на сторону браузера код JavaScript.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
!ВНИМАНИЕ! Данная функция поддерживает передачу переменных в область кода JavaScript (*inArgList). Обратиться к переданным переменным из JavaScript можно с помощью ключевого слова: arguments[i], где i - это порядковый номер переданной переменной
@@ -169,6 +223,8 @@ def BrowserClose():
def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list:
"""L+,W+: Получить список UIO объектов по UIO селектору.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -176,7 +232,7 @@ def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list:
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIOList = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
@@ -204,6 +260,8 @@ def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list:
def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list:
"""L+,W+: Получить UIO объект по UIO селектору.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -211,7 +269,7 @@ def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list:
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorFirst(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
@@ -229,6 +287,8 @@ def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list:
def UIOTextGet(inUIO) -> str:
"""L+,W+: Получить текст UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -236,7 +296,7 @@ def UIOTextGet(inUIO) -> str:
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
lTextStr = UIWeb.UIOTextGet(inUIO=lUIO)
UIWeb.BrowserClose()
@@ -250,6 +310,8 @@ def UIOTextGet(inUIO) -> str:
def UIOAttributeGet(inUIO, inAttributeStr) -> str:
"""L+,W+: Получить обычный (нестилевой) атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -257,7 +319,7 @@ def UIOAttributeGet(inUIO, inAttributeStr) -> str:
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeGet(inUIO=lUIO, inAttributeStr = "href")
UIWeb.BrowserClose()
@@ -273,6 +335,8 @@ def UIOAttributeGet(inUIO, inAttributeStr) -> str:
def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str:
"""L+,W+: Получить стилевой атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -280,7 +344,7 @@ def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str:
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleGet(inUIO=lUIO, inAttributeStr = "href")
UIWeb.BrowserClose()
@@ -296,6 +360,8 @@ def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str:
def UIOAttributeSet(inUIO, inAttributeStr, inValue):
"""L+,W+: Установить обычный (нестилевой) атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -303,7 +369,7 @@ def UIOAttributeSet(inUIO, inAttributeStr, inValue):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeSet(inUIO=lUIO, inAttributeStr = "href", inValue = "https://mail.ru")
UIWeb.BrowserClose()
@@ -321,6 +387,8 @@ def UIOAttributeSet(inUIO, inAttributeStr, inValue):
def UIOAttributeRemove(inUIO, inAttributeStr):
"""L+,W+: Удалить обычный (нестилевой) атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -328,7 +396,7 @@ def UIOAttributeRemove(inUIO, inAttributeStr):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeRemove(lUIO, "href")
UIWeb.BrowserClose()
@@ -344,6 +412,8 @@ def UIOAttributeRemove(inUIO, inAttributeStr):
def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue):
"""L+,W+: Установить стилевой атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -351,7 +421,7 @@ def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleSet(inUIO=lUIO, inAttributeStr = "color", inValue = "grey")
UIWeb.BrowserClose()
@@ -369,6 +439,8 @@ def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue):
def UIOAttributeStyleRemove(inUIO, inAttributeStr:str):
"""L+,W+: Удалить стилевой атрибут у UI элемента.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -376,7 +448,7 @@ def UIOAttributeStyleRemove(inUIO, inAttributeStr:str):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleRemove(lUIO, "color")
UIWeb.BrowserClose()
@@ -392,6 +464,8 @@ def UIOAttributeStyleRemove(inUIO, inAttributeStr:str):
def UIOClick(inUIO):
"""L+,W+: Выполнить нажатие по элементу inUIO.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -399,7 +473,7 @@ def UIOClick(inUIO):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIOClick(inUIO = lUIO)
UIWeb.BrowserClose()
@@ -411,6 +485,8 @@ def UIOClick(inUIO):
def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDurationSecFloat:float=3.0, inColorStr:str="green"):
"""L+,W+: Выполнить подсвечивание UI элемента с селектором inUIOSelectorStr.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -418,7 +494,7 @@ def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDuration
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
UIWeb.UIOSelectorHighlight(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
@@ -467,6 +543,8 @@ def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDuration
def UIOSelectorClick(inUIOSelectorStr: str):
"""L+,W+: Выполнить нажатие по элементу с селектором inUIOSelectorStr.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -474,25 +552,56 @@ def UIOSelectorClick(inUIOSelectorStr: str):
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
UIWeb.UIOSelectorClick(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
:param inUIOSelectorStr: XPATH или CSS селектор UI элемента на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath
:type inUIOSelectorStr: str
"""
- PageJSExecute(inJSStr=f"document.querySelector('{inUIOSelectorStr}').click()")
+ if UIOSelectorDetect(inUIOSelectorStr=inUIOSelectorStr) == "CSS":
+ PageJSExecute(inJSStr=f"document.querySelector('{inUIOSelectorStr}').click()")
+ else:
+ PageJSExecute(inJSStr=f"document.evaluate('{inUIOSelectorStr}', document, null , XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click()")
+
+def UIOSelectorSetValue(inUIOSelectorStr: str, inValue: str):
+ """L+,W+: Установить значение элемента с селектором inUIOSelectorStr.
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
+
+ .. code-block:: python
+ # UIWeb: Взаимодействие с ui web
+ from pyOpenRPA.Robot import UIWeb
+ UIWeb.BrowserChromeStart()
+ UIWeb.PageOpen("https://www.google.com/")
+ lUIOSelectorStr = "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input"
+ lValue = "pyOpenRPA"
+ UIWeb.UIOSelectorSetValue(inUIOSelectorStr = lUIOSelectorStr, inValue = lValue)
+ UIWeb.BrowserClose()
+
+ :param inUIOSelectorStr: XPATH или CSS селектор UI элемента на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath
+ :type inUIOSelectorStr: str
+ :param inValue: Значение, которое необходимо установить
+ :type inValue: str
+ """
+ if UIOSelectorDetect(inUIOSelectorStr=inUIOSelectorStr) == "CSS":
+ PageJSExecute(inJSStr=f"document.querySelector('{inUIOSelectorStr}').value='{inValue}'")
+ else:
+ PageJSExecute(inJSStr=f"document.evaluate('{inUIOSelectorStr}', document, null , XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value='{inValue}'")
+
def UIOSelectorWaitAppear(inUIOSelectorStr:str, inWaitSecFloat:float=UIO_WAIT_SEC_FLOAT, inWaitIntervalSecFloat:float = UIO_WAIT_INTERVAL_SEC_FLOAT):
"""L+,W+: Ожидать появление UI элемента на веб странице (блокирует выполнение потока), заданного по UIO селектору inUIOSelectorStr. Выполнять ожидание на протяжении inWaitSecFloat (по умолчанию 60 сек.). Проверка производится с интервалом inWaitIntervalSecFloat (по умолчанию 1 сек.)
-
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
+
.. code-block:: python
# UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lAppearUIOList = UIWeb.UIOSelectorWaitAppear(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
@@ -517,14 +626,16 @@ def UIOSelectorWaitAppear(inUIOSelectorStr:str, inWaitSecFloat:float=UIO_WAIT_SE
def UIOSelectorWaitDisappear(inUIOSelectorStr:str, inWaitSecFloat:float=UIO_WAIT_SEC_FLOAT, inWaitIntervalSecFloat:float = UIO_WAIT_INTERVAL_SEC_FLOAT):
"""L+,W+: Ожидать исчезновение UI элемента с веб страницы (блокирует выполнение потока), заданного по UIO селектору inUIOSelectorStr. Выполнять ожидание на протяжении inWaitSecFloat (по умолчанию 60 сек.). Проверка производится с интервалом inWaitIntervalSecFloat (по умолчанию 1 сек.)
-
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
+
.. code-block:: python
# UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru")
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
UIWeb.UIOSelectorWaitDisappear(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose()
@@ -556,7 +667,7 @@ def UIOSelectorDetect(inUIOSelectorStr:str) -> str:
# UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb
lUIOSelectorStr = "#grid > div.grid-middle > div.grid__main-col.svelte-2y66pa > div.grid_newscol.grid_newscol__more-pulse.svelte-1yvqfic > div.grid__ccol.svelte-1yvqfic > ul > li:nth-child(5) > div > a"
- lUIOSelectorStr = "//*[@id=\"grid\"]/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
+ lUIOSelectorStr = "//*[@id=\'grid\']/div[2]/div[2]/div[3]/div[1]/ul/li[5]/div/a"
lResultStr = UIWeb.UIOSelectorDetect(inUIOSelectorStr = lUIOSelectorStr)
:param inUIOSelectorStr: XPATH или CSS селектор UI объекта на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath
@@ -576,6 +687,8 @@ def UIOSelectorDetect(inUIOSelectorStr:str) -> str:
def UIOMouseSearchInit():
"""L+,W+: Инициализирует процесс поиска UI элемента с помощью мыши. Для прекращения поиска необходимо использовать функцию: UIOMouseSearchReturn
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -603,6 +716,8 @@ def UIOMouseSearchInit():
def UIOMouseSearchReturn():
"""L+,W+: Возвращает UIO объект, над которым находится указатель мыши. Предварительно должна быть вызвана функция UIWeb.UIOMouseSearchInit
+
+ !ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python
@@ -623,5 +738,7 @@ def UIOMouseSearchReturn():
document.removeEventListener('mousemove', document.ORPASearch);
return document.elementFromPoint(document.ORPAMouseXInt,document.ORPAMouseYInt);
"""
- return PageJSExecute(lJSStr)
+ try:
+ return PageJSExecute(lJSStr)
+ except JavascriptException: raise JavascriptException("Отсутствуют координаты для идентификации веб-элемента. Пожалуйста, в следующий раз двигайте мышью")
\ No newline at end of file
diff --git a/Sources/setup.py b/Sources/setup.py
index fca6d516..7451a3b0 100755
--- a/Sources/setup.py
+++ b/Sources/setup.py
@@ -69,6 +69,7 @@ setup(name='pyOpenRPA',
'fastapi>=0.81.0',
'uvicorn>=0.18.3',
'python-multipart>=0.0.6'
+ 'autodocsumm>=0.2.10'
],
extras_require={
':sys_platform == "win32"': [
diff --git a/Tools/Jupyter-notebooks/start.cmd b/Tools/Jupyter-notebooks/start.cmd
index 6f9fbd43..49547a08 100755
--- a/Tools/Jupyter-notebooks/start.cmd
+++ b/Tools/Jupyter-notebooks/start.cmd
@@ -1,3 +1,3 @@
chcp 65001
call init-python-env.cmd jupyter-notebook.exe jupyter-notebook.exe
-jupyter-notebook.exe -m notebook --notebook-dir=%~dp0
\ No newline at end of file
+jupyter-notebook.exe -m notebook --notebook-dir="%~dp0
diff --git a/changelog.md b/changelog.md
index ce53e791..0888046f 100755
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,10 @@ AGT - AGENT
******************************
- ОБЩЕЕ
- - Utils: Disk - подготовка файлов / папок, если они не обнаружены (полезно при первом запуске, если требуются БД/ Файлы хранилищ)
+- - Jupyter: запуск из директорий, пути к которым содержат пробелы
+- - PyOpenRPA: autodocsumm - добавлено к пакетам
+- - Исправлено неправильное поведение оркестратора при авторизации в браузере Firefox
+- - Исправлено описание функци в документации, раздел UIWeb
- ОРКЕСТРАТОР
- - Исправление совместимости URL путей с некорыми ресурсами для отработки в LINUX
- - Поддержка многотысячной аудитории, одновременно работающей в панели управления (async server-data server-log with fastapi)
@@ -22,9 +26,19 @@ AGT - AGENT
- - AgentProcessList исправление (hotfix)
- - Права доступа в случае незаявленного пользователя (Hotfix)
- - Возможность авторизации в формате login@domain
+- - Переработана система обработки AuthTokenStr==None. Теперь поднимается exception в случаях, когда авторизация производилась, но AuthTokenStr==None
+- - Добавлена новая функция - Orchestrator.OrchestratorIsCredentialsAsk. Определяет была ли произведена авторизация пользователя
+- - WebURLConnectFolder - переработано. Добавлен флаг обработки ошибки, позволяющий продолжить инициализацию оркестратора, если папки не существует
+- - Переработана система авторизации. Добавлена стартовая страница оркестратора с формой для ввода пары логин / пароль
- РОБОТ
- - Убрали лишний print из Screen.BoxAnchorRuleCheck
-
+- - pyOpenRPA.Robot.UIWeb.BrowserChromeStart - добавлен флаг печати в PDF и директория для сохранения при инициализации браузера
+- - Добавлена новая функция - pyOpenRPA.Robot.UIWeb.PagePrint. Вызывает окно печати браузера
+- - pyOpenRPA.Robot.UIWeb.UIOSelectorClick - исправлено. Теперь работает и с XPath, и с CSS
+- - Добавлена новая функция - pyOpenRPA.Robot.UIWeb.UIOSelectorSetValue. Изменение атрибута value по заданному UIOSelector элемента
+- - pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOList - исправлена обработка exceptions. Теперь флаг ловит все исключения
+- - Флаг inFlagRaiseException добавлен во все функции, связанные с pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOList. Теперь режим работы с исключениями задается глобально. Исключения отлавливаются - inFlagRaiseException=True, не отлавливаются - inFlagRaiseException=False
+- - pyOpenRPA.Robot.UIWeb.UIOMouseSearchReturn добавлена обработка JavascriptException
[1.3.1]
- ОРКЕСТРАТОР
- - минорные правки в дизайн