Merge branch 'dev-floidd' into 'dev-fastapi'

BugFixes merge request

See merge request UnicodeLabs/OpenRPA!2
dev-fastapi
commit d7d0395a11

@ -44,7 +44,7 @@ else:
Orchestrator.OrchestratorLoggerGet().setLevel(logging.INFO) Orchestrator.OrchestratorLoggerGet().setLevel(logging.INFO)
# TEST Add User ND - Add Login ND to superuser of the Orchestrator # TEST Add User ND - Add Login ND to superuser of the Orchestrator
lUACClientDict = SettingsTemplate.__UACClientAdminCreate__() lUACClientDict = SettingsTemplate.__UACClientAdminCreate__()
gSettings["ServerDict"]["AccessUsers"]["FlagCredentialsAsk"]=False gSettings["ServerDict"]["AccessUsers"]["FlagCredentialsAsk"]=True
Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="ND", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict) Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="ND", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict)
Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="rpa00", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict) Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="rpa00", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict)
# TEST Add User IMaslov - Add Login IMaslov to superuser of the Orchestrator # TEST Add User IMaslov - Add Login IMaslov to superuser of the Orchestrator

@ -18,9 +18,11 @@ from . import ServerBC
# объявление import # объявление import
from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response, Body from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response, Body
from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse, RedirectResponse, JSONResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from fastapi.encoders import jsonable_encoder
from starlette.datastructures import MutableHeaders
from pydantic import BaseModel from pydantic import BaseModel
import uvicorn import uvicorn
import io import io
@ -28,6 +30,7 @@ from starlette.responses import StreamingResponse
from typing import Union from typing import Union
from pyOpenRPA import __version__ from pyOpenRPA import __version__
import requests
import base64 import base64
import uuid import uuid
import datetime import datetime
@ -43,6 +46,8 @@ app = FastAPI(
swagger_ui_oauth2_redirect_url = "/orpa/fastapi/docs/oauth2-redirect", swagger_ui_oauth2_redirect_url = "/orpa/fastapi/docs/oauth2-redirect",
) )
def IdentifyAuthorize(inRequest:Request, inResponse:Response, def IdentifyAuthorize(inRequest:Request, inResponse:Response,
inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"), inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"),
inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")): inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")):
@ -70,9 +75,11 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
return lCookieAuthToken return lCookieAuthToken
###################################### ######################################
#Way 2 - try to logon #Way 2 - try to logon
if len(lHeaderAuthorization) == 2: if lHeaderAuthorization != ['']:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( if "AuthExc" in lCookies:
":") raise AuthException()
else:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[0]).decode("utf-8").split(":")
lUser = llHeaderAuthorizationDecodedUserPasswordList[0] lUser = llHeaderAuthorizationDecodedUserPasswordList[0]
lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] lPassword = llHeaderAuthorizationDecodedUserPasswordList[1]
lDomain = "" lDomain = ""
@ -108,22 +115,22 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
mOpenRPA["Domain"] = lResult["Domain"] mOpenRPA["Domain"] = lResult["Domain"]
mOpenRPA["User"] = lResult["User"] mOpenRPA["User"] = lResult["User"]
mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False)
return lAuthToken raise ReloadPage(token=lAuthToken)
#inRequest.OpenRPASetCookie = {} #inRequest.OpenRPASetCookie = {}
#New engine of server #New engine of server
#inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (для пользователя не заявлен доступ к оркестратору pyOpenRPA. Обратитесь в техническую поддержку)", headers={}) errorMsg = "Попытка авторизации не прошла успешно (для пользователя не заявлен доступ к оркестратору pyOpenRPA. Обратитесь в техническую поддержку)"
raise ErrorException(text=errorMsg)
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неверная пара логин / пароль)", headers={}) errorMsg = "Попытка авторизации не прошла успешно (неверная пара логин / пароль)"
###################################### raise ErrorException(text=errorMsg)
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неполная пара логин / пароль)", headers={'Content-type':'text/html', 'WWW-Authenticate':'Basic'}) raise AuthException()
else: return None # Credentials are not required - return none else: return None # Credentials are not required - return none
# Перевод встроенных fastapi функций на авторизацию
lRouteList =[] lRouteList =[]
for lItem in app.router.routes: for lItem in app.router.routes:
lRouteList.append(lItem) lRouteList.append(lItem)
@ -137,6 +144,49 @@ for lItem in lRouteList:
tags=["FastAPI"] tags=["FastAPI"]
) )
# объявление классов для дальнейшей обработки вызываемых исключений (обязательно должны наследоваться от EXception)
class ErrorException(Exception):
def __init__(self, text :str, name: str="AuthExc"):
self.name = name
self.text = text
class AuthException(Exception):
def __init__(self, name: str="AuthTryWindowCreate"):
self.name = name
class ReloadPage(Exception):
def __init__(self, token :str, name: str="AuthToken"):
self.name = name
self.token = token
templates = Jinja2Templates(directory=CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-2] + ["Resources","Web","orpa"]))
# Обработчик ошибки авторизации (вывод информации о причинах неудачной авторизации)
@app.exception_handler(ErrorException)
async def unicorn_exception_handler(request: Request, exc:ErrorException):
response = templates.TemplateResponse(status_code=401,name="badAuth.xhtml", context={"request":request, "errorMsg":exc.text, "title":"ОРКЕСТРАТОР PYOPENRPA", "subtitle":"АВТОРИЗАЦИЯ", "version":__version__})
response.set_cookie(key="AuthExc",value="True")
return response
# Обработчик успешной попытки авторизации (обновление страницы + установки куки-токена)
@app.exception_handler(ReloadPage)
async def unicorn_exception_handler_3(request: Request, exc:ReloadPage):
response = HTMLResponse(content="", status_code=200)
response.set_cookie(key=exc.name, value=exc.token)
try:response.delete_cookie(key="AuthExc")
except Exception:pass
return response
# Обработчик попытки авторизации (отвечает за рендер формы для ввода пары логин / пароль)
@app.exception_handler(AuthException)
def unicorn_exception_handler_2(request: Request, exc: AuthException):
response = templates.TemplateResponse(status_code=401,name="auth.xhtml", context={"request":request, "title":"ОРКЕСТРАТОР PYOPENRPA", "subtitle":"АВТОРИЗАЦИЯ", "version":__version__})
try:response.delete_cookie(key="AuthExc")
except Exception:pass
return response
from . import ServerSettings from . import ServerSettings
@ -185,13 +235,17 @@ def InitFastAPI():
ServerSettings.SettingsUpdate() ServerSettings.SettingsUpdate()
BCURLUpdate() BCURLUpdate()
def BCURLUpdate(): def BCURLUpdate(inExceptionFlagBool:bool=True):
for lConnectItemDict in __Orchestrator__.GSettingsGet()["ServerDict"]["URLList"]: for lConnectItemDict in __Orchestrator__.GSettingsGet()["ServerDict"]["URLList"]:
if "BCBool" not in lConnectItemDict: if "BCBool" not in lConnectItemDict:
if "ResponseFolderPath" in lConnectItemDict: if "ResponseFolderPath" in lConnectItemDict:
try:
app.mount(lConnectItemDict["URL"], app.mount(lConnectItemDict["URL"],
StaticFiles(directory=CrossOS.PathStr(lConnectItemDict["ResponseFolderPath"])), StaticFiles(directory=CrossOS.PathStr(lConnectItemDict["ResponseFolderPath"])),
name=lConnectItemDict["URL"].replace('/',"_")) name=lConnectItemDict["URL"].replace('/',"_"))
except:
if inExceptionFlagBool: raise RuntimeError("Fatal error. Bad FolderPath")
else: pass
else: else:
if lConnectItemDict.get("MatchType") in ["BeginWith", "EqualCase", "Equal","EqualNoParam"]: if lConnectItemDict.get("MatchType") in ["BeginWith", "EqualCase", "Equal","EqualNoParam"]:
if lConnectItemDict.get("UACBool",True): if lConnectItemDict.get("UACBool",True):

@ -498,7 +498,7 @@ def SettingsUpdate():
#} #}
#Orchestrator basic dependencies # Index page in server.py because of special settings #Orchestrator basic dependencies # Index page in server.py because of special settings
{"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index}, {"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index},
{"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources\\Web\\orpa\\metadata.json")), "ResponseContentType": "application/json"}, {"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources\\Web\\orpa\\metadata.json")), "ResponseContentType": "application/json","UACBool":False,},
#{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"}, #{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"},
{"Method":"GET", "URL": "/orpa/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources")),"UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/orpa/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources")),"UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/orpa/client/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "Web"),"UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/orpa/client/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "Web"),"UACBool":False, "UseCacheBool": True},

@ -623,6 +623,14 @@ def OrchestratorIsAdmin():
elif CrossOS.IS_LINUX_BOOL: return os.getuid()==0 elif CrossOS.IS_LINUX_BOOL: return os.getuid()==0
else: return True else: return True
def OrchestratorIsCredentialsAsk():
"""L+,W+: Проверить, активирована ли авторизация при переходе к Оркестратору.
:return: True - Активирована; False - Деактивирована
"""
inGSettings = GSettingsGet()
return inGSettings["ServerDict"]["AccessUsers"]["FlagCredentialsAsk"]
def OrchestratorIsInited() -> bool: def OrchestratorIsInited() -> bool:
"""L+,W+: Проверить, было ли проинициализировано ядро Оркестратора """L+,W+: Проверить, было ли проинициализировано ядро Оркестратора
@ -1069,6 +1077,11 @@ def WebUserLoginGet(inAuthTokenStr: str=None) -> str:
:return: Логин пользователя :return: Логин пользователя
:rtype: str :rtype: str
""" """
isCredentialAsk = OrchestratorIsCredentialsAsk()
if isCredentialAsk:
if inAuthTokenStr is None: raise ConnectionError("Не удается получить токен для авторизации")
else:
if inAuthTokenStr is None: return None if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("User", None) return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("User", None)
@ -1082,17 +1095,21 @@ def WebUserDomainGet(inAuthTokenStr: str=None) -> str:
:rtype: str :rtype: str
""" """
isCredentialAsk = OrchestratorIsCredentialsAsk()
if isCredentialAsk:
if inAuthTokenStr is None: raise ConnectionError("Не удается получить токен для авторизации")
else:
if inAuthTokenStr is None: return None if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("Domain", None) return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("Domain", None)
def WebUserInfoGet(inAuthTokenStr=None): def WebUserInfoGet(inAuthTokenStr=None):
"""L+,W+: Информация о пользователе, который отправил HTTP запрос. """L+,W+: Информация о пользователе, который отправил HTTP запрос.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"} :return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"}
""" """
try: try:
lResultDict = { lResultDict = {
"DomainUpperStr": WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper(), "DomainUpperStr": WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper(),
@ -1109,6 +1126,7 @@ def WebUserIsSuperToken(inAuthTokenStr: str=None):
:type inAuthTokenStr: str, опционально :type inAuthTokenStr: str, опционально
:return: True - является супертокеном; False - не является супертокеном; None - авторизация не производилась :return: True - является супертокеном; False - не является супертокеном; None - авторизация не производилась
""" """
if inAuthTokenStr is None: return None if inAuthTokenStr is None: return None
inGSettings = GSettingsGet() # Get the global settings inGSettings = GSettingsGet() # Get the global settings
lIsSuperTokenBool = False lIsSuperTokenBool = False
@ -1123,7 +1141,13 @@ def WebUserUACHierarchyGet(inAuthTokenStr: str=None) -> dict:
:type inAuthTokenStr: str, опционально :type inAuthTokenStr: str, опционально
:return: UAC словарь доступа или {}, что означает полный доступ :return: UAC словарь доступа или {}, что означает полный доступ
""" """
isCredentialAsk = OrchestratorIsCredentialsAsk()
if isCredentialAsk:
if inAuthTokenStr is None: raise ConnectionError("Не удается получить токен для авторизации")
else:
if inAuthTokenStr is None: return {} if inAuthTokenStr is None: return {}
lDomainUpperStr = WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper() lDomainUpperStr = WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper()
lUserUpperStr = WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper() lUserUpperStr = WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper()
if lUserUpperStr is None: return {} if lUserUpperStr is None: return {}
@ -1137,7 +1161,14 @@ def WebUserUACCheck(inAuthTokenStr:str=None, inKeyList:list=None) -> bool:
:return: True - доступ имеется, False - доступа нет :return: True - доступ имеется, False - доступа нет
:rtype: bool :rtype: bool
""" """
if inAuthTokenStr is None: return True # Если авторизации не происходило - супердоступ
isCredentialAsk = OrchestratorIsCredentialsAsk()
# Если авторизации не происходило - супердоступ
if isCredentialAsk:
if inAuthTokenStr is None: return False
else:
if inAuthTokenStr is None: return True
lResult = True # Init flag lResult = True # Init flag
lRoleHierarchyDict = WebUserUACHierarchyGet(inAuthTokenStr=inAuthTokenStr) # get the Hierarchy lRoleHierarchyDict = WebUserUACHierarchyGet(inAuthTokenStr=inAuthTokenStr) # get the Hierarchy
# Try to get value from key list # Try to get value from key list
@ -1192,13 +1223,14 @@ def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentType
Server.BCURLUpdate() Server.BCURLUpdate()
def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inGSettings = None, inUACBool = None, inUseCacheBool= False): def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inExceptionFlagBool=False, inGSettings = None, inUACBool = None, inUseCacheBool= False):
"""L+,W+: Подключить папку к URL. """L+,W+: Подключить папку к URL.
:param inMethodStr: Метод доступа по URL "GET" || "POST" :param inMethodStr: Метод доступа по URL "GET" || "POST"
:param inURLStr: URL адрес. Пример "/index" :param inURLStr: URL адрес. Пример "/index"
:param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam"
:param inFolderPathStr: Путь к папке на диске, в которой искать файл и возвращать пользователю по HTTP :param inFolderPathStr: Путь к папке на диске, в которой искать файл и возвращать пользователю по HTTP
:param inExceptionFlagBool: Флаг на обработку ошибки. True - показывать ошибку в терминале (остановка инициализации), False - не показывать
:param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя
:param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать :param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
@ -1220,7 +1252,7 @@ def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr,
"UseCacheBool": inUseCacheBool "UseCacheBool": inUseCacheBool
} }
inGSettings["ServerDict"]["URLList"].append(lURLItemDict) inGSettings["ServerDict"]["URLList"].append(lURLItemDict)
Server.BCURLUpdate() Server.BCURLUpdate(inExceptionFlagBool)
def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings = None, inUACBool = None, inUseCacheBool = False): def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings = None, inUACBool = None, inUseCacheBool = False):

@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<!-- Yandex.Metrika counter -->
<script async="" src="https://mc.yandex.ru/metrika/tag.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88079149, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/88079149" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Оркестратор pyOpenRPA</title>
<meta name="description" content="Ведущий RPA разработчик российского программного обеспечения. RPA платформа позволяет решать любые бизнес-задачи. Комплексное решение от компании RPA pyOpenRPA. Первое открытое российское RPA решение для крупного / среднего / малого бизнеса. Доступная автоматизация для каждого." />
<meta name="keywords" content="rpa, программные роботы, автоматизация бизнес-процессов, цифровые сотрудники, виртуальные сотрудники" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/orpa/styleset/home.css" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script
src="/orpa/resources/Web/jQuery/jquery-3.1.1.min.js"
crossorigin="anonymous"></script>
<script src="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.js"></script>
<script src="/orpa/resources/Web/Handlebars/handlebars-v4.1.2.js"></script>
</head>
<style type="text/css">
h4 {
display: inline-block;
}
button.ui.green.button {
font-family:'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
background: #368279
}
</style>
<body>
{% include 'header.xhtml' %}
<center>
<div class="ui placeholder segment">
<div class="ui icon header">
<i class="user icon"></i>
Для доступа к панели управления, пожалуйста, пройдите авторизацию
</div>
<div class="inline">
<br />
<div class="head"><h4 class="ui header">
<div align="left">Логин от учетной записи</div>
<div class="ui input">
<input type="text" class="headIn" name="uname" style="width: 400px;" autocomplete="off" onchange="inputFormCheck()"/>
</div>
</h4></div>
<br />
<div class="head"><h4 class="ui header">
<div align="left">Пароль от учетной записи</div>
<div class="ui input">
<input type="password" class="headIn" id="pasInp" name="pasw" style="width: 400px;" autocomplete="off" onchange="inputFormCheck()" />
</div>
</h4></div>
<div class="pasChbView" align="left">
<label><input type="checkbox" class="pasChb" /> Показать пароль</label>
</div>
<br />
<button class="ui green button" id="logBtn" onclick="do_auth()" style="width: 200px;">Войти</button>
</div>
</div>
</center>
{% include 'footer.xhtml' %}
<script type="text/javascript">
async function do_auth() {
var uname = document.getElementsByClassName("headIn")[0].value
var psw = document.getElementsByClassName("headIn")[1].value
var authByteArray = (uname+":"+psw).toString('utf8')
getText(authByteArray);
}
async function getText(authByteArray) {
const response = await fetch("/",{
method: "GET",
headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization":btoa(authByteArray)},
credentials: "include"
});
const responseText = await response.text();
if (response.ok) {
location.reload()
}
else {
document.querySelector('html').innerHTML = responseText
}
}
function inputFormCheck() {
var inputForms = document.getElementsByClassName("headIn")
var flag = false
for (var i = 0; i < inputForms.length; i++) {
result = inputForms[i].value.match(/[А-Я]/gi)
if (result) {
flag = true
document.getElementsByClassName("headIn")[i].style.backgroundColor = "#F08080"
}
else {
document.getElementsByClassName("headIn")[i].style.backgroundColor = "white"
}
}
if (flag) {
document.getElementById("logBtn").disabled = true
}
else {
document.getElementById("logBtn").disabled = false
}
}
$('body').on('click', '.pasChb', function(){
if ($(this).is(':checked')){
$('#pasInp').attr('type', 'text');
} else {
$('#pasInp').attr('type', 'password');
}
});
</script>
</body>
<style type="text/css">
.ui.footer.segment {
margin: 0em 0em 0em;
padding: 5.05em 0em;
}
</style>
</html>

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<!-- Yandex.Metrika counter -->
<script async="" src="https://mc.yandex.ru/metrika/tag.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88079149, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/88079149" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Оркестратор pyOpenRPA</title>
<meta name="description" content="Ведущий RPA разработчик российского программного обеспечения. RPA платформа позволяет решать любые бизнес-задачи. Комплексное решение от компании RPA pyOpenRPA. Первое открытое российское RPA решение для крупного / среднего / малого бизнеса. Доступная автоматизация для каждого." />
<meta name="keywords" content="rpa, программные роботы, автоматизация бизнес-процессов, цифровые сотрудники, виртуальные сотрудники" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/orpa/styleset/home.css" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script
src="/orpa/resources/Web/jQuery/jquery-3.1.1.min.js"
crossorigin="anonymous"></script>
<script src="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.js"></script>
<script src="/orpa/resources/Web/Handlebars/handlebars-v4.1.2.js"></script>
</head>
<style type="text/css">
button.ui.green.button {
font-family:'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
background: #368279
}
</style>
<body>
{% include 'header.xhtml' %}
<br /><br /><br /><br /><br />
<center>
<div class="ui message">
<div class="header">Внимание</div>
<p>{{errorMsg}}</p>
</div>
<button class="ui green button" onclick="document.location='/'" style="width: 200px;">Повторить попытку</button>
</center>
{% include 'footer.xhtml' %}
</body>
<style type="text/css">
.ui.footer.segment {
margin: 10.7em 0em 0em;
padding: 5em 0em;
}
</style>
</html>

@ -1,21 +1,21 @@
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/reset.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/reset.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/site.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/site.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/container.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/container.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/grid.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/grid.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/header.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/header.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/image.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/image.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/menu.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/menu.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/divider.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/divider.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/dropdown.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/dropdown.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/segment.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/segment.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/button.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/button.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/list.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/list.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/icon.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/icon.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/sidebar.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/sidebar.css" />
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/transition.css"> <link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/components/transition.css" />
<div class="pusher tag-top"> <div class="pusher tag-top">

@ -120,7 +120,7 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
:type inSpecificationList: list, обязательный :type inSpecificationList: list, обязательный
:param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии :param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии
:type inElement: UIO объект, опциональный :type inElement: UIO объект, опциональный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный :type inFlagRaiseException: bool, опциональный
:return: Список UIO объектов, которые удовлетворяют условиям UIO селектора :return: Список UIO объектов, которые удовлетворяют условиям UIO селектора
''' '''
@ -128,6 +128,7 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
inSpecificationList=copy.deepcopy(inSpecificationList) inSpecificationList=copy.deepcopy(inSpecificationList)
lResultList=[] lResultList=[]
lChildrenList=[] lChildrenList=[]
try:
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
if inElement is None: if inElement is None:
#сформировать спецификацию на получение элемента #сформировать спецификацию на получение элемента
@ -245,6 +246,9 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
if inElement is None and len(lResultList)==0 and inFlagRaiseException: if inElement is None and len(lResultList)==0 and inFlagRaiseException:
raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector") raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector")
return lResultList return lResultList
except Exception as e:
if inFlagRaiseException: raise e
else: return []
#old:PywinautoExtElementGet #old:PywinautoExtElementGet
def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException=True): def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException=True):
@ -268,16 +272,13 @@ def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException
''' '''
lResult=None lResult=None
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
lResultList=UIOSelector_Get_UIOList(inSpecificationList,inElement,False) lResultList=UIOSelector_Get_UIOList(inSpecificationList,inElement,inFlagRaiseException)
if len(lResultList)>0: if len(lResultList)>0:
lResult=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 return lResult
#old:- #old:-
def UIOSelector_Exist_Bool (inUIOSelector): def UIOSelector_Exist_Bool (inUIOSelector, inFlagRaiseException=True):
'''L-,W+: Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору '''L-,W+: Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -292,6 +293,8 @@ def UIOSelector_Exist_Bool (inUIOSelector):
:param inUIOSelector: UIO Селектор, который определяет критерии поиска UIO объектов :param inUIOSelector: UIO Селектор, который определяет критерии поиска UIO объектов
:type inUIOSelector: list, обязательный :type inUIOSelector: list, обязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:return: True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору :return: True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору
''' '''
lResult=False lResult=False
@ -299,7 +302,9 @@ def UIOSelector_Exist_Bool (inUIOSelector):
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None: 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: if len(lResultList)>0:
lResult=True lResult=True
else: else:
@ -319,7 +324,7 @@ def UIOSelector_Exist_Bool (inUIOSelector):
return lResult return lResult
#old: - #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 селекторам '''L-,W+: Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -342,6 +347,8 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
:type inSpecificationListList: list, обязательный :type inSpecificationListList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд) :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный :type inWaitSecs: float, необязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области
:return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]
''' '''
@ -356,7 +363,7 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
#Итерация проверки #Итерация проверки
lIndex = 0 lIndex = 0
for lItem in inSpecificationListList: for lItem in inSpecificationListList:
lItemResultFlag=UIOSelector_Exist_Bool(lItem) lItemResultFlag=UIOSelector_Exist_Bool(lItem, inFlagRaiseException=True)
#Если обнаружен элемент - добавить его индекс в массив #Если обнаружен элемент - добавить его индекс в массив
if lItemResultFlag: if lItemResultFlag:
lResultList.append(lIndex) lResultList.append(lIndex)
@ -376,7 +383,7 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0
return lResultList return lResultList
#old: - #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 селекторам '''L-,W+: Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -399,6 +406,8 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
:type inSpecificationListList: list, обязательный :type inSpecificationListList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд) :param inWaitSecs: Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный :type inWaitSecs: float, необязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области
:return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]
''' '''
@ -414,7 +423,7 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
#Итерация проверки #Итерация проверки
lIndex = 0 lIndex = 0
for lItem in inSpecificationListList: for lItem in inSpecificationListList:
lItemResultFlag=UIOSelector_Exist_Bool(lItem) lItemResultFlag=UIOSelector_Exist_Bool(lItem,inFlagRaiseException=inFlagRaiseException)
#Если обнаружен элемент - добавить его индекс в массив #Если обнаружен элемент - добавить его индекс в массив
if not lItemResultFlag: if not lItemResultFlag:
lResultList.append(lIndex) lResultList.append(lIndex)
@ -434,7 +443,7 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=8640
return lResultList return lResultList
#old: - #old: -
def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs): def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs, inFlagRaiseException=True):
'''L-,W+: Ожидать появление 1-го UIO объекта по заданному UIO селектору '''L-,W+: Ожидать появление 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -451,16 +460,18 @@ def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs):
:type inSpecificationList: list, обязательный :type inSpecificationList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд) :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный :type inWaitSecs: float, необязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:return: True - UIO объект был обнаружен. False - обратная ситуациая :return: True - UIO объект был обнаружен. False - обратная ситуациая
''' '''
lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs) lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs, inFlagRaiseException=inFlagRaiseException)
lResult=False lResult=False
if len(lWaitAppearList)>0: if len(lWaitAppearList)>0:
lResult=True lResult=True
return lResult return lResult
#old name - - #old name - -
def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs): def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs,inFlagRaiseException=True):
'''L-,W+: Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору '''L-,W+: Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -477,9 +488,11 @@ def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs):
:type inSpecificationList: list, обязательный :type inSpecificationList: list, обязательный
:param inWaitSecs: Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд) :param inWaitSecs: Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд)
:type inWaitSecs: float, необязательный :type inWaitSecs: float, необязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:return: True - UIO объект был обнаружен. False - обратная ситуациая :return: True - UIO объект был обнаружен. False - обратная ситуациая
''' '''
lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs) lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs,inFlagRaiseException=inFlagRaiseException)
lResult=False lResult=False
if len(lWaitDisappearList)>0: if len(lWaitDisappearList)>0:
lResult=True lResult=True
@ -908,7 +921,7 @@ def UIO_GetCtrlIndex_Int(inElement):
return lResult return lResult
#old: - PywinautoExtElementsGetInfo #old: - PywinautoExtElementsGetInfo
def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None): def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None, inFlagRaiseException=True):
"""L-,W+: Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement. """L-,W+: Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -925,13 +938,15 @@ def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None):
:type inUIOSelector: list, обязательный :type inUIOSelector: list, обязательный
:param inElement: UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений. :param inElement: UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений.
:type inElement: UIO объект, необязательный :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} :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 #Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None: if lSafeOtherProcess is None:
#Получить родительский объект если на вход ничего не поступило #Получить родительский объект если на вход ничего не поступило
lResultList=UIOSelector_Get_UIOList(inUIOSelector, inElement) lResultList=UIOSelector_Get_UIOList(inUIOSelector, inElement, inFlagRaiseException)
lIterator = 0 lIterator = 0
for lItem in lResultList: for lItem in lResultList:
lResultList[lIterator]=UIOEI_Convert_UIOInfo(lResultList[lIterator].element_info) lResultList[lIterator]=UIOEI_Convert_UIOInfo(lResultList[lIterator].element_info)
@ -985,7 +1000,7 @@ def UIOSelector_TryRestore_Dict(inSpecificationList):
return lResult return lResult
#old: - ElementActionGetList #old: - ElementActionGetList
def UIOSelector_Get_UIOActivityList (inUIOSelector): def UIOSelector_Get_UIOActivityList (inUIOSelector,inFlagRaiseException=True):
"""L-,W+: Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже. """L-,W+: Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -1000,12 +1015,14 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector):
:param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.
:type inUIOSelector: list, обязательный :type inUIOSelector: list, обязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
""" """
#Check the bitness #Check the bitness
lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector)
if lSafeOtherProcess is None: if lSafeOtherProcess is None:
#Получить объект #Получить объект
lObject=UIOSelector_Get_UIO(inUIOSelector) lObject=UIOSelector_Get_UIO(inUIOSelector,inFlagRaiseException=inFlagRaiseException)
lActionList=dir(lObject) lActionList=dir(lObject)
lResult=dir(lObject) lResult=dir(lObject)
#Выполнить чистку списка от неактуальных методов #Выполнить чистку списка от неактуальных методов
@ -1033,7 +1050,7 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector):
return lResult return lResult
#old: - ElementRunAction #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. Описание возможных активностей см. ниже. """L-,W+: Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector. Описание возможных активностей см. ниже.
!ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())
@ -1050,6 +1067,8 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=
:type inUIOSelector: list, обязательный :type inUIOSelector: list, обязательный
:param inActionName: наименование активности, которую требуется выполнить над UIO объектом :param inActionName: наименование активности, которую требуется выполнить над UIO объектом
:type inActionName: str, обязательный :type inActionName: str, обязательный
:param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай (может привести к ошибочным результатам). По умолчанию True.
:type inFlagRaiseException: bool, опциональный
:param inArgumentList: список передаваемых неименованных аргументов в функцию inActionName :param inArgumentList: список передаваемых неименованных аргументов в функцию inActionName
:type inArgumentList: list, необязательный :type inArgumentList: list, необязательный
:param inkwArgumentObject: словарь передаваемых именованных аргументов в функцию inActionName :param inkwArgumentObject: словарь передаваемых именованных аргументов в функцию inActionName
@ -1064,7 +1083,7 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=
#Run activity if SafeOtherProcess is None #Run activity if SafeOtherProcess is None
if lSafeOtherProcess is None: if lSafeOtherProcess is None:
#Определить объект #Определить объект
lObject=UIOSelector_Get_UIO(inUIOSelector) lObject=UIOSelector_Get_UIO(inUIOSelector,inFlagRaiseException=inFlagRaiseException)
#Получить метод для вызова #Получить метод для вызова
lFunction = getattr(lObject, inActionName) lFunction = getattr(lObject, inActionName)
#Выполнить действие #Выполнить действие

@ -1,8 +1,10 @@
from selenium import * from selenium import *
from selenium import webdriver, common from selenium import webdriver, common
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.common.exceptions import JavascriptException
import os import os
import sys import sys
import json
from pyOpenRPA.Tools import CrossOS from pyOpenRPA.Tools import CrossOS
import time import time
@ -14,8 +16,8 @@ UIO_WAIT_INTERVAL_SEC_FLOAT = 1.0
gBrowser:webdriver.Chrome = None gBrowser:webdriver.Chrome = None
def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = None, inExtensionPathList:list = None, inProfilePathStr:str=None) -> webdriver.Chrome: 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. """L+,W+: Выполнить запуск браузера Chrome. Если вы скачали pyOpenRPA вместе с репозиторием, то будет использоваться встроенный браузер Google Chrome. Если установка pyOpenRPA производилась другим способом, то требуется указать расположение браузера Google Chrome и соответствующего WebDriver
.. code-block:: python .. code-block:: python
@ -32,6 +34,10 @@ def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = N
:type inExtensionPathList: list, опционально :type inExtensionPathList: list, опционально
:param inProfilePathStr: Путь, по которому выполнить сохранения профиля Chrome (история, куки и т.д.), по умолчанию None (профиль не сохраняется) :param inProfilePathStr: Путь, по которому выполнить сохранения профиля Chrome (история, куки и т.д.), по умолчанию None (профиль не сохраняется)
:type inProfilePathStr: str, опционально :type inProfilePathStr: str, опционально
:param inSaveAsPDFBool: Флаг, который обеспечивает настройки окна печати вэб-страницы как "Сохранить как PDF", по умолчанию False (настройки по умолчанию)
:type inSaveAsPDFBool: bool, опционально
:param inSavefileDefaultDirStr: Путь, по которому выполнить сохранения файла (после работы с окном печать вэб-страницы браузера) (история, куки и т.д.), по умолчанию None (файл не сохраняется)
:type inSavefileDefaultDirStr: str, опционально
:return: Объект браузера Google Chrome :return: Объект браузера Google Chrome
:rtype: webdriver.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") 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") elif CrossOS.IS_LINUX_BOOL: inChromeExePathStr = os.path.join(lResourcePathStr, "LChrome64-10305060114", "data", "chrome")
if inExtensionPathList == None: inExtensionPathList = [] if inExtensionPathList == None: inExtensionPathList = []
# Set full path to exe of the chrome # Установка настроек окна печати, если необходимо
lWebDriverChromeOptionsInstance = webdriver.ChromeOptions() 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 lWebDriverChromeOptionsInstance.binary_location = inChromeExePathStr
#lWebDriverChromeOptionsInstance2 = webdriver.ChromeOptions() #lWebDriverChromeOptionsInstance2 = webdriver.ChromeOptions()
if inProfilePathStr is not None: if inProfilePathStr is not None:
@ -94,6 +123,8 @@ def BrowserChange(inBrowser):
def PageOpen(inURLStr: str): def PageOpen(inURLStr: str):
"""L+,W+: Открыть страницу inURLStr в браузере и дождаться ее загрузки. """L+,W+: Открыть страницу inURLStr в браузере и дождаться ее загрузки.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
@ -108,9 +139,30 @@ def PageOpen(inURLStr: str):
global gBrowser global gBrowser
if gBrowser is not None: gBrowser.get(inURLStr) 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): def PageScrollTo(inVerticalPxInt=0, inHorizontalPxInt=0):
"""L+,W+: Выполнить прокрутку страницы (по вертикали или по горизонтали) """L+,W+: Выполнить прокрутку страницы (по вертикали или по горизонтали)
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
@ -130,6 +182,8 @@ def PageScrollTo(inVerticalPxInt=0, inHorizontalPxInt=0):
def PageJSExecute(inJSStr, *inArgList): def PageJSExecute(inJSStr, *inArgList):
"""L+,W+: Отправить на выполнение на сторону браузера код JavaScript. """L+,W+: Отправить на выполнение на сторону браузера код JavaScript.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
!ВНИМАНИЕ! Данная функция поддерживает передачу переменных в область кода JavaScript (*inArgList). Обратиться к переданным переменным из JavaScript можно с помощью ключевого слова: arguments[i], где i - это порядковый номер переданной переменной !ВНИМАНИЕ! Данная функция поддерживает передачу переменных в область кода JavaScript (*inArgList). Обратиться к переданным переменным из JavaScript можно с помощью ключевого слова: arguments[i], где i - это порядковый номер переданной переменной
.. code-block:: python .. code-block:: python
@ -170,13 +224,15 @@ def BrowserClose():
def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list: def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list:
"""L+,W+: Получить список UIO объектов по UIO селектору. """L+,W+: Получить список UIO объектов по UIO селектору.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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) lUIOList = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -205,13 +261,15 @@ def UIOSelectorList(inUIOSelectorStr, inUIO=None) -> list:
def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list: def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list:
"""L+,W+: Получить UIO объект по UIO селектору. """L+,W+: Получить UIO объект по UIO селектору.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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) lUIO = UIWeb.UIOSelectorFirst(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -230,13 +288,15 @@ def UIOSelectorFirst(inUIOSelectorStr, inUIO=None) -> list:
def UIOTextGet(inUIO) -> str: def UIOTextGet(inUIO) -> str:
"""L+,W+: Получить текст UI элемента. """L+,W+: Получить текст UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
lTextStr = UIWeb.UIOTextGet(inUIO=lUIO) lTextStr = UIWeb.UIOTextGet(inUIO=lUIO)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -251,13 +311,15 @@ def UIOTextGet(inUIO) -> str:
def UIOAttributeGet(inUIO, inAttributeStr) -> str: def UIOAttributeGet(inUIO, inAttributeStr) -> str:
"""L+,W+: Получить обычный (нестилевой) атрибут у UI элемента. """L+,W+: Получить обычный (нестилевой) атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeGet(inUIO=lUIO, inAttributeStr = "href") UIWeb.UIOAttributeGet(inUIO=lUIO, inAttributeStr = "href")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -274,13 +336,15 @@ def UIOAttributeGet(inUIO, inAttributeStr) -> str:
def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str: def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str:
"""L+,W+: Получить стилевой атрибут у UI элемента. """L+,W+: Получить стилевой атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleGet(inUIO=lUIO, inAttributeStr = "href") UIWeb.UIOAttributeStyleGet(inUIO=lUIO, inAttributeStr = "href")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -297,13 +361,15 @@ def UIOAttributeStyleGet(inUIO, inAttributeStr) -> str:
def UIOAttributeSet(inUIO, inAttributeStr, inValue): def UIOAttributeSet(inUIO, inAttributeStr, inValue):
"""L+,W+: Установить обычный (нестилевой) атрибут у UI элемента. """L+,W+: Установить обычный (нестилевой) атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeSet(inUIO=lUIO, inAttributeStr = "href", inValue = "https://mail.ru") UIWeb.UIOAttributeSet(inUIO=lUIO, inAttributeStr = "href", inValue = "https://mail.ru")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -322,13 +388,15 @@ def UIOAttributeSet(inUIO, inAttributeStr, inValue):
def UIOAttributeRemove(inUIO, inAttributeStr): def UIOAttributeRemove(inUIO, inAttributeStr):
"""L+,W+: Удалить обычный (нестилевой) атрибут у UI элемента. """L+,W+: Удалить обычный (нестилевой) атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeRemove(lUIO, "href") UIWeb.UIOAttributeRemove(lUIO, "href")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -345,13 +413,15 @@ def UIOAttributeRemove(inUIO, inAttributeStr):
def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue): def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue):
"""L+,W+: Установить стилевой атрибут у UI элемента. """L+,W+: Установить стилевой атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleSet(inUIO=lUIO, inAttributeStr = "color", inValue = "grey") UIWeb.UIOAttributeStyleSet(inUIO=lUIO, inAttributeStr = "color", inValue = "grey")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -370,13 +440,15 @@ def UIOAttributeStyleSet(inUIO, inAttributeStr, inValue):
def UIOAttributeStyleRemove(inUIO, inAttributeStr:str): def UIOAttributeStyleRemove(inUIO, inAttributeStr:str):
"""L+,W+: Удалить стилевой атрибут у UI элемента. """L+,W+: Удалить стилевой атрибут у UI элемента.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIWeb.UIOAttributeStyleRemove(lUIO, "color") UIWeb.UIOAttributeStyleRemove(lUIO, "color")
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -393,13 +465,15 @@ def UIOAttributeStyleRemove(inUIO, inAttributeStr:str):
def UIOClick(inUIO): def UIOClick(inUIO):
"""L+,W+: Выполнить нажатие по элементу inUIO. """L+,W+: Выполнить нажатие по элементу inUIO.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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] lUIO = UIWeb.UIOSelectorList(inUIOSelectorStr = lUIOSelectorStr)[0]
UIOClick(inUIO = lUIO) UIOClick(inUIO = lUIO)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -412,13 +486,15 @@ def UIOClick(inUIO):
def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDurationSecFloat:float=3.0, inColorStr:str="green"): def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDurationSecFloat:float=3.0, inColorStr:str="green"):
"""L+,W+: Выполнить подсвечивание UI элемента с селектором inUIOSelectorStr. """L+,W+: Выполнить подсвечивание UI элемента с селектором inUIOSelectorStr.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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.UIOSelectorHighlight(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -468,31 +544,64 @@ def UIOSelectorHighlight(inUIOSelectorStr: str, inIsFirst:bool=False, inDuration
def UIOSelectorClick(inUIOSelectorStr: str): def UIOSelectorClick(inUIOSelectorStr: str):
"""L+,W+: Выполнить нажатие по элементу с селектором inUIOSelectorStr. """L+,W+: Выполнить нажатие по элементу с селектором inUIOSelectorStr.
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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.UIOSelectorClick(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
:param inUIOSelectorStr: XPATH или CSS селектор UI элемента на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath :param inUIOSelectorStr: XPATH или CSS селектор UI элемента на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath
:type inUIOSelectorStr: str :type inUIOSelectorStr: str
""" """
if UIOSelectorDetect(inUIOSelectorStr=inUIOSelectorStr) == "CSS":
PageJSExecute(inJSStr=f"document.querySelector('{inUIOSelectorStr}').click()") 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): 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 сек.) """L+,W+: Ожидать появление UI элемента на веб странице (блокирует выполнение потока), заданного по UIO селектору inUIOSelectorStr. Выполнять ожидание на протяжении inWaitSecFloat (по умолчанию 60 сек.). Проверка производится с интервалом inWaitIntervalSecFloat (по умолчанию 1 сек.)
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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) lAppearUIOList = UIWeb.UIOSelectorWaitAppear(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -518,13 +627,15 @@ 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): 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 сек.) """L+,W+: Ожидать исчезновение UI элемента с веб страницы (блокирует выполнение потока), заданного по UIO селектору inUIOSelectorStr. Выполнять ожидание на протяжении inWaitSecFloat (по умолчанию 60 сек.). Проверка производится с интервалом inWaitIntervalSecFloat (по умолчанию 1 сек.)
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.PageOpen("https://mail.ru") 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.UIOSelectorWaitDisappear(inUIOSelectorStr = lUIOSelectorStr)
UIWeb.BrowserClose() UIWeb.BrowserClose()
@ -556,7 +667,7 @@ def UIOSelectorDetect(inUIOSelectorStr:str) -> str:
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
from pyOpenRPA.Robot import UIWeb 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 = "#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) lResultStr = UIWeb.UIOSelectorDetect(inUIOSelectorStr = lUIOSelectorStr)
:param inUIOSelectorStr: XPATH или CSS селектор UI объекта на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath :param inUIOSelectorStr: XPATH или CSS селектор UI объекта на web странице. Подсказки по CSS: https://devhints.io/css Подсказки по XPath: https://devhints.io/xpath
@ -577,6 +688,8 @@ def UIOSelectorDetect(inUIOSelectorStr:str) -> str:
def UIOMouseSearchInit(): def UIOMouseSearchInit():
"""L+,W+: Инициализирует процесс поиска UI элемента с помощью мыши. Для прекращения поиска необходимо использовать функцию: UIOMouseSearchReturn """L+,W+: Инициализирует процесс поиска UI элемента с помощью мыши. Для прекращения поиска необходимо использовать функцию: UIOMouseSearchReturn
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
@ -604,6 +717,8 @@ def UIOMouseSearchInit():
def UIOMouseSearchReturn(): def UIOMouseSearchReturn():
"""L+,W+: Возвращает UIO объект, над которым находится указатель мыши. Предварительно должна быть вызвана функция UIWeb.UIOMouseSearchInit """L+,W+: Возвращает UIO объект, над которым находится указатель мыши. Предварительно должна быть вызвана функция UIWeb.UIOMouseSearchInit
!ВНИМАНИЕ! Для работы необходимо проинициализировать webdriver
.. code-block:: python .. code-block:: python
# UIWeb: Взаимодействие с ui web # UIWeb: Взаимодействие с ui web
@ -623,5 +738,7 @@ def UIOMouseSearchReturn():
document.removeEventListener('mousemove', document.ORPASearch); document.removeEventListener('mousemove', document.ORPASearch);
return document.elementFromPoint(document.ORPAMouseXInt,document.ORPAMouseYInt); return document.elementFromPoint(document.ORPAMouseXInt,document.ORPAMouseYInt);
""" """
try:
return PageJSExecute(lJSStr) return PageJSExecute(lJSStr)
except JavascriptException: raise JavascriptException("Отсутствуют координаты для идентификации веб-элемента. Пожалуйста, в следующий раз двигайте мышью")

@ -69,6 +69,7 @@ setup(name='pyOpenRPA',
'fastapi>=0.81.0', 'fastapi>=0.81.0',
'uvicorn>=0.18.3', 'uvicorn>=0.18.3',
'python-multipart>=0.0.6' 'python-multipart>=0.0.6'
'autodocsumm>=0.2.10'
], ],
extras_require={ extras_require={
':sys_platform == "win32"': [ ':sys_platform == "win32"': [

@ -1,3 +1,3 @@
chcp 65001 chcp 65001
call init-python-env.cmd jupyter-notebook.exe jupyter-notebook.exe call init-python-env.cmd jupyter-notebook.exe jupyter-notebook.exe
jupyter-notebook.exe -m notebook --notebook-dir=%~dp0 jupyter-notebook.exe -m notebook --notebook-dir="%~dp0

@ -11,6 +11,10 @@ AGT - AGENT
****************************** ******************************
- ОБЩЕЕ - ОБЩЕЕ
- - Utils: Disk - подготовка файлов / папок, если они не обнаружены (полезно при первом запуске, если требуются БД/ Файлы хранилищ) - - Utils: Disk - подготовка файлов / папок, если они не обнаружены (полезно при первом запуске, если требуются БД/ Файлы хранилищ)
- - Jupyter: запуск из директорий, пути к которым содержат пробелы
- - PyOpenRPA: autodocsumm - добавлено к пакетам
- - Исправлено неправильное поведение оркестратора при авторизации в браузере Firefox
- - Исправлено описание функци в документации, раздел UIWeb
- ОРКЕСТРАТОР - ОРКЕСТРАТОР
- - Исправление совместимости URL путей с некорыми ресурсами для отработки в LINUX - - Исправление совместимости URL путей с некорыми ресурсами для отработки в LINUX
- - Поддержка многотысячной аудитории, одновременно работающей в панели управления (async server-data server-log with fastapi) - - Поддержка многотысячной аудитории, одновременно работающей в панели управления (async server-data server-log with fastapi)
@ -22,9 +26,19 @@ AGT - AGENT
- - AgentProcessList исправление (hotfix) - - AgentProcessList исправление (hotfix)
- - Права доступа в случае незаявленного пользователя (Hotfix) - - Права доступа в случае незаявленного пользователя (Hotfix)
- - Возможность авторизации в формате login@domain - - Возможность авторизации в формате login@domain
- - Переработана система обработки AuthTokenStr==None. Теперь поднимается exception в случаях, когда авторизация производилась, но AuthTokenStr==None
- - Добавлена новая функция - Orchestrator.OrchestratorIsCredentialsAsk. Определяет была ли произведена авторизация пользователя
- - WebURLConnectFolder - переработано. Добавлен флаг обработки ошибки, позволяющий продолжить инициализацию оркестратора, если папки не существует
- - Переработана система авторизации. Добавлена стартовая страница оркестратора с формой для ввода пары логин / пароль
- РОБОТ - РОБОТ
- - Убрали лишний print из Screen.BoxAnchorRuleCheck - - Убрали лишний 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] [1.3.1]
- ОРКЕСТРАТОР - ОРКЕСТРАТОР
- - минорные правки в дизайн - - минорные правки в дизайн

Loading…
Cancel
Save