# Update Python x32 and x64 to v.1.1.8 - need test

dev-linux
Ivan Maslov 5 years ago
parent 4c8d0e3187
commit 2460a9162d

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.1.7
Version: 1.1.8
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,14 +1,14 @@
pyOpenRPA-1.1.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.7.dist-info/METADATA,sha256=1-INEcLwD0cOjRbapwir23aemV9ibQZ4wV4TiXRPjic,3541
pyOpenRPA-1.1.7.dist-info/RECORD,,
pyOpenRPA-1.1.7.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.7.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA-1.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.8.dist-info/METADATA,sha256=1_HsS23rWQTlrtEYmKKcXIypmIc9mBeIonMYsr-5Mg0,3541
pyOpenRPA-1.1.8.dist-info/RECORD,,
pyOpenRPA-1.1.8.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.8.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
pyOpenRPA/.idea/pyOpenRPA.iml,sha256=EXh41F8lqRiSBMVg-n2tKaEaHC6_3gGSuKkPJA12Na0,408
pyOpenRPA/.idea/vcs.xml,sha256=2HygA1oRAwc3VBf-irxHrX5JJG9DXuQwrN0BlubhoKY,191
pyOpenRPA/.idea/workspace.xml,sha256=b6vLBJkXjoocb4ZXHCdzrfzL2o6PuG7x_3qJ14Va9-U,2754
pyOpenRPA/.idea/workspace.xml,sha256=kcCP7x0iSOAWJdy7YtntGrgsQ04QIq0b6_9w04DKxfg,2555
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iVp7DlLZHsURBOBegfDG4LanqSrI0A5a6GebP1cBOnI,8301
pyOpenRPA/Orchestrator/Processor.py,sha256=ur0jDDteyBzfXR4DXnpUfBwNEW-M2nEtgyd-HQoPVtQ,11376
@ -33,10 +33,10 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Server.py,sha256=I8xt39oyC5A05rrS3-1yBAXYJfrG_iT1ZIbVUmrD_0g,25483
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=v63ELppzsBx7U-90fLg8CrG2EAqjNXnObPi5E3ZPo34,7757
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=yPIAa6jr3VVzWXiL59LEVaaGPrKglkVzxtACpb-HOwA,38637
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=EFW6jPs0trHyQeKtJ8hKEEeZN9JBBkIJpjfpSI6b0Qs,36442
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -225,7 +225,7 @@ pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx
pyOpenRPA/Robot/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476
pyOpenRPA/Robot/UIDesktop.py,sha256=V7Hb53MJHPhOF8tZhG1zwM9zOEWA4nMe2Bq0NHjmhbU,78284
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
@ -300,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=m5yh4PYhwUL7CDaoIiQC7iIbXn8LQ2tjTyPUFQx6Ulo,174
pyOpenRPA/__init__.py,sha256=SsoRpEVSVmt8ZyoFr9X7q2UjunxaTzfc1Qmr0IP9PNs,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -22,6 +22,8 @@ from http import cookies
global gSettingsDict
from . import ServerSettings
import copy
#Authenticate function ()
# return dict
# {
@ -33,10 +35,6 @@ def AuthenticateVerify(inRequest):
######################################
#Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
inRequest.OpenRPA = {}
inRequest.OpenRPA["AuthToken"] = None
inRequest.OpenRPA["Domain"] = None
inRequest.OpenRPA["User"] = None
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -193,6 +191,34 @@ def UserAccessCheckBefore(inMethod, inRequest):
return lResult
# HTTPRequestHandler class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to check User Role access grants
def UserRoleAccessAsk(self, inRoleKeyList):
lResult = True # Init flag
lRoleHierarchyDict = self.UserRoleHierarchyGet() # get the Hierarchy
# Try to get value from key list
lKeyValue = lRoleHierarchyDict # Init the base
for lItem in inRoleKeyList:
if type(lKeyValue) is dict:
if lItem in lKeyValue: # Has key
lKeyValue = lKeyValue[lItem] # Get the value and go to the next loop iteration
else: # Else branch - true or false
if len(lKeyValue)>0: # False - if Dict has some elements
lResult = False # Set the False Flag
else:
lResult = True # Set the True flag
break # Stop the loop
else: # Has element with no detalization - return True
lResult = True # Set the flag
break # Close the loop
return lResult # Return the result
# Def to get hierarchy of the current user roles
# if return {} - all is available
def UserRoleHierarchyGet(self):
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
#Tech def
#return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod):
@ -287,6 +313,12 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
self.wfile.write(inResponseDict["Body"])
def do_GET(self):
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict
lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None}
self.OpenRPAResponseDict = lResponseDict
@ -350,6 +382,13 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
self.end_headers()
# POST
def do_POST(self):
lL = gSettingsDict["Logger"]
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict
#pdb.set_trace()
lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None}
@ -360,8 +399,14 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
lIsSuperToken = False # Is supertoken
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
# Get Flag is supertoken (True|False)
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
lIsSuperToken = gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(
(lDomainUpperStr, lUserUpperStr), {}).get("FlagDoNotExpire", False)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
if lFlagAccessUserBlock:
@ -401,6 +446,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers
self.send_header('Content-type','application/json')
self.end_headers()
# Logging info about processor activity if not SuperToken ()
if not lIsSuperToken:
if lL: lL.info(f"Server:: User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, Activity: {lInputObject}")
# Send message back to client
message = json.dumps(Processor.ActivityListOrDict(lInputObject))
# Write content as utf-8 data

@ -47,6 +47,16 @@ def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
# UserAccess get rights hierarchy dict in json
def UserRoleHierarchyGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict
# Create result JSON
lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list
# Send message back to client
message = json.dumps(lResultDict)
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
def GetScreenshot(inRequest,inGlobalDict):
# Get Screenshot
def SaveScreenshot(inFilePath):
@ -90,7 +100,8 @@ def SettingsUpdate(inGlobalConfiguration):
{"Method":"GET", "URL": "/3rdParty/Handlebars/handlebars-v4.1.2.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js"), "ResponseContentType": "application/javascript"},
{"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": Monitor_ControlPanelDictGet, "ResponseContentType": "application/json"},
{"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"},
{"Method": "GET", "URL": "/Orchestrator/RobotRDPActive/ControlPanelDictGet", "MatchType": "Equal","ResponseDefRequestGlobal": RobotRDPActive_ControlPanelDictGet, "ResponseContentType": "application/json"}
{"Method": "GET", "URL": "/Orchestrator/RobotRDPActive/ControlPanelDictGet", "MatchType": "Equal","ResponseDefRequestGlobal": RobotRDPActive_ControlPanelDictGet, "ResponseContentType": "application/json"},
{"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": UserRoleHierarchyGet, "ResponseContentType": "application/json"}
]
inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
return inGlobalConfiguration

@ -388,37 +388,6 @@
dataType: "text"
});
}
///////////////////////////////
///Scheduler functions
///////////////////////////////
mGlobal.Scheduler = {}
mGlobal.Scheduler.ActivityTimeListShow = function() {
lData = [
{
"Type":"GlobalDictKeyListValueGet",
"KeyList":["Scheduler","ActivityTimeList"]
}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
lResponseJSON[0]["Result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])})
///Отправить запрос на формирование таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON[0]);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
},
dataType: "text"
});
}
///////////////////////////////
///Processor functions
///////////////////////////////
@ -507,32 +476,6 @@
dataType: "text"
});
}
mGlobal.Processor.LogListShow = function() {
lData = [
{
"Type":"GlobalDictKeyListValueGet",
"KeyList":["Processor","LogList"]
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-activitylogschedulelist",lResponseJSON["actionListResult"][0])
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
},
dataType: "text"
});
}
mGlobal.Server= {}
mGlobal.Server.JSONGet=function(inMethod, inURL, inDataJSON, inCallback)
{
@ -661,6 +604,37 @@
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
// Check user roles and update the Orchestrator UI
mGlobal.UserRoleUpdate=function() {
$.ajax({
type: "POST",
url: 'Orchestrator/UserRoleHierarchyGet',
data: "",
success:
function(lData,l2,l3)
{
var lResponseDict=JSON.parse(lData)
//Turn on the Lookmachine screenshot button
var lDict = ((lResponseDict["Orchestrator"] || {})["Controls"] || {}) // Get the Controls dict
if ("LookMachineScreenshots" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-control-lookmachinescreenshot").show() //Show button
}
//Turn on the restart orchestrator button
var lDict = ((lResponseDict["Orchestrator"] || {})["Controls"] || {}) // Get the Controls dict
if ("RestartOrchestrator" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-control-restartorchestrator").show() //Show button
}
//Turn on the rdp session list
var lDict = ((lResponseDict["Orchestrator"] || {})["RDPActive"] || {}) // Get the Controls dict
if ("ListRead" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-rdpactive-title").show() //Show section
$(".openrpa-robotrdpactive-control-panel-general").show() //Show section
}
},
dataType: "text"
});
}
mGlobal.UserRoleUpdate() // Cal the update User Roles function
})
;
</script>
@ -781,75 +755,20 @@
<h2 class="ui header inverted">...</h2>
</div>
<div class="nine wide column">
<h2 class="ui header inverted">Robot RDP active list</h2>
<h2 class="ui header inverted openrpa-rdpactive-title" style="display:none;">Robot RDP active list</h2>
</div>
</div>
<div class="row">
<div class="five wide column">
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
<button class="ui labeled icon button openrpa-control-lookmachinescreenshot" onclick="mGlobal.Monitor.ScreenshotModal.Show();" style="display: none;">
<i class="desktop icon"></i>
Look machine screenshot
</button>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
<button class="ui labeled icon button red openrpa-control-restartorchestrator" onclick="mGlobal.Controller.OrchestratorRestart(); " style="display: none;>
<i class="redo icon"></i>
Restart Orchestrator
</button>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<i class="info icon"></i>
Scheduler activity time list
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Time</th>
<th>Process path/Process name</th>
</tr>
</thead>
<tbody>
{{#Result}}
<tr>
<td>{{@index}}</td>
<td>{{TimeHH:MM}}{{TimeHH:MMStart}}</td>
<td>{{TimeHH:MMStop}}</td>
<td>{{Activity}}</td>
</tr>
{{/Result}}
</tbody>
</table>
</script>
</button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i>
Processor logs
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Process</th>
<th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr>
</thead>
<tbody>
{{#result}}
<tr>
<td>{{@index}}</td>
<td>{{activityType}}</td>
<td>{{processPath}}</td>
<td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr>
{{/result}}
</tbody>
</table>
</script>
</button>
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
@ -927,7 +846,7 @@
</div>
<div class="two wide column">
</div>
<div class="nine wide column openrpa-robotrdpactive-control-panel-general">
<div class="nine wide column openrpa-robotrdpactive-control-panel-general" style="display:none;">
<div class="ui info message">
<button class="ui icon button labeled " onclick="mGlobal.RobotRDPActive.fControlPanelRefresh();">
<i class="sync alternate icon"></i>

@ -118,7 +118,15 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
#Елемент на вход поступил - выполнить его анализ
else:
#Получить список элементов
lElementChildrenList=inElement.children()
lElementChildrenList = None
# 2020 06 10 Some times exception ctypes.ArgumentError is apper - set try except with wait
lFlagBool = True
while lFlagBool:
try:
lElementChildrenList = inElement.children()
lFlagBool = False # turn off the loop - all is ok
except ctypes.ArgumentError as e:
time.sleep(30) # error has come - go in sleep and retry
#Поступил index - точное добавление
if 'index' in inSpecificationList[0]:
if inSpecificationList[0]['index']<len(lElementChildrenList):
@ -444,7 +452,15 @@ def PWASpecification_Get_UIO(inControlSpecificationArray):
lTempObject=None
if len(inControlSpecificationArray) > 0:
#Сформировать выборку элементов, которые подходят под первый уровень спецификации
# 2020 06 10 Some times exception ctypes.ArgumentError is apper - set try except with wait
lSpecificationLvL1List = None
lFlagBool = True
while lFlagBool:
try:
lSpecificationLvL1List = pywinauto.findwindows.find_elements(**inControlSpecificationArray[0])
lFlagBool = False # turn off the loop - all is ok
except ctypes.ArgumentError as e:
time.sleep(30) # error has come - go in sleep and retry
for lItem in lSpecificationLvL1List:
#Сделать независимую копию и установить информацию о process_id и handle
lItemControlSpecificationArray=copy.deepcopy(inControlSpecificationArray)

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.7'
__version__ = 'v1.1.8'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pyOpenRPA
Version: 1.1.7
Version: 1.1.8
Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov

@ -1,14 +1,14 @@
pyOpenRPA-1.1.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.7.dist-info/METADATA,sha256=1-INEcLwD0cOjRbapwir23aemV9ibQZ4wV4TiXRPjic,3541
pyOpenRPA-1.1.7.dist-info/RECORD,,
pyOpenRPA-1.1.7.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.7.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA-1.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.8.dist-info/METADATA,sha256=1_HsS23rWQTlrtEYmKKcXIypmIc9mBeIonMYsr-5Mg0,3541
pyOpenRPA-1.1.8.dist-info/RECORD,,
pyOpenRPA-1.1.8.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.8.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
pyOpenRPA/.idea/pyOpenRPA.iml,sha256=EXh41F8lqRiSBMVg-n2tKaEaHC6_3gGSuKkPJA12Na0,408
pyOpenRPA/.idea/vcs.xml,sha256=2HygA1oRAwc3VBf-irxHrX5JJG9DXuQwrN0BlubhoKY,191
pyOpenRPA/.idea/workspace.xml,sha256=b6vLBJkXjoocb4ZXHCdzrfzL2o6PuG7x_3qJ14Va9-U,2754
pyOpenRPA/.idea/workspace.xml,sha256=kcCP7x0iSOAWJdy7YtntGrgsQ04QIq0b6_9w04DKxfg,2555
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/Orchestrator/Orchestrator.py,sha256=iVp7DlLZHsURBOBegfDG4LanqSrI0A5a6GebP1cBOnI,8301
pyOpenRPA/Orchestrator/Processor.py,sha256=ur0jDDteyBzfXR4DXnpUfBwNEW-M2nEtgyd-HQoPVtQ,11376
@ -33,10 +33,10 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=gqJO6FRDKTBZytJVdJgPF1PvOf05qYUyKDBJJkEpLzk,22755
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=mpPAxAe6PvmKaZlreaoQAy_5wV80edz_0qc-iFrEmBQ,7123
pyOpenRPA/Orchestrator/Server.py,sha256=I8xt39oyC5A05rrS3-1yBAXYJfrG_iT1ZIbVUmrD_0g,25483
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=v63ELppzsBx7U-90fLg8CrG2EAqjNXnObPi5E3ZPo34,7757
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=yPIAa6jr3VVzWXiL59LEVaaGPrKglkVzxtACpb-HOwA,38637
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=EFW6jPs0trHyQeKtJ8hKEEeZN9JBBkIJpjfpSI6b0Qs,36442
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=0vdsnwKGh6pgB0FDB5mOKO7RwbxQ9F13Zg16F1pkvXs,5430
pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144
@ -225,7 +225,7 @@ pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx
pyOpenRPA/Robot/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476
pyOpenRPA/Robot/UIDesktop.py,sha256=V7Hb53MJHPhOF8tZhG1zwM9zOEWA4nMe2Bq0NHjmhbU,78284
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
@ -300,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=m5yh4PYhwUL7CDaoIiQC7iIbXn8LQ2tjTyPUFQx6Ulo,174
pyOpenRPA/__init__.py,sha256=SsoRpEVSVmt8ZyoFr9X7q2UjunxaTzfc1Qmr0IP9PNs,174
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -22,6 +22,8 @@ from http import cookies
global gSettingsDict
from . import ServerSettings
import copy
#Authenticate function ()
# return dict
# {
@ -33,10 +35,6 @@ def AuthenticateVerify(inRequest):
######################################
#Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
inRequest.OpenRPA = {}
inRequest.OpenRPA["AuthToken"] = None
inRequest.OpenRPA["Domain"] = None
inRequest.OpenRPA["User"] = None
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -193,6 +191,34 @@ def UserAccessCheckBefore(inMethod, inRequest):
return lResult
# HTTPRequestHandler class
class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to check User Role access grants
def UserRoleAccessAsk(self, inRoleKeyList):
lResult = True # Init flag
lRoleHierarchyDict = self.UserRoleHierarchyGet() # get the Hierarchy
# Try to get value from key list
lKeyValue = lRoleHierarchyDict # Init the base
for lItem in inRoleKeyList:
if type(lKeyValue) is dict:
if lItem in lKeyValue: # Has key
lKeyValue = lKeyValue[lItem] # Get the value and go to the next loop iteration
else: # Else branch - true or false
if len(lKeyValue)>0: # False - if Dict has some elements
lResult = False # Set the False Flag
else:
lResult = True # Set the True flag
break # Stop the loop
else: # Has element with no detalization - return True
lResult = True # Set the flag
break # Close the loop
return lResult # Return the result
# Def to get hierarchy of the current user roles
# if return {} - all is available
def UserRoleHierarchyGet(self):
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
#Tech def
#return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod):
@ -287,6 +313,12 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
self.wfile.write(inResponseDict["Body"])
def do_GET(self):
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict
lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None}
self.OpenRPAResponseDict = lResponseDict
@ -350,6 +382,13 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
self.end_headers()
# POST
def do_POST(self):
lL = gSettingsDict["Logger"]
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict
#pdb.set_trace()
lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None}
@ -360,8 +399,14 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#####################################
lFlagAccessUserBlock=False
lAuthenticateDict = {"Domain": "", "User": ""}
lIsSuperToken = False # Is supertoken
if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False):
lAuthenticateDict = AuthenticateVerify(self)
# Get Flag is supertoken (True|False)
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
lIsSuperToken = gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(
(lDomainUpperStr, lUserUpperStr), {}).get("FlagDoNotExpire", False)
if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True
if lFlagAccessUserBlock:
@ -401,6 +446,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers
self.send_header('Content-type','application/json')
self.end_headers()
# Logging info about processor activity if not SuperToken ()
if not lIsSuperToken:
if lL: lL.info(f"Server:: User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, Activity: {lInputObject}")
# Send message back to client
message = json.dumps(Processor.ActivityListOrDict(lInputObject))
# Write content as utf-8 data

@ -47,6 +47,16 @@ def Monitor_ControlPanelDictGet(inRequest,inGlobalDict):
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
# UserAccess get rights hierarchy dict in json
def UserRoleHierarchyGet(inRequest,inGlobalDict):
inResponseDict = inRequest.OpenRPAResponseDict
# Create result JSON
lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list
# Send message back to client
message = json.dumps(lResultDict)
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
def GetScreenshot(inRequest,inGlobalDict):
# Get Screenshot
def SaveScreenshot(inFilePath):
@ -90,7 +100,8 @@ def SettingsUpdate(inGlobalConfiguration):
{"Method":"GET", "URL": "/3rdParty/Handlebars/handlebars-v4.1.2.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js"), "ResponseContentType": "application/javascript"},
{"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": Monitor_ControlPanelDictGet, "ResponseContentType": "application/json"},
{"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"},
{"Method": "GET", "URL": "/Orchestrator/RobotRDPActive/ControlPanelDictGet", "MatchType": "Equal","ResponseDefRequestGlobal": RobotRDPActive_ControlPanelDictGet, "ResponseContentType": "application/json"}
{"Method": "GET", "URL": "/Orchestrator/RobotRDPActive/ControlPanelDictGet", "MatchType": "Equal","ResponseDefRequestGlobal": RobotRDPActive_ControlPanelDictGet, "ResponseContentType": "application/json"},
{"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": UserRoleHierarchyGet, "ResponseContentType": "application/json"}
]
inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList
return inGlobalConfiguration

@ -388,37 +388,6 @@
dataType: "text"
});
}
///////////////////////////////
///Scheduler functions
///////////////////////////////
mGlobal.Scheduler = {}
mGlobal.Scheduler.ActivityTimeListShow = function() {
lData = [
{
"Type":"GlobalDictKeyListValueGet",
"KeyList":["Scheduler","ActivityTimeList"]
}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
lResponseJSON[0]["Result"].forEach(function(lItem){lItem["processPathName"]=("processPath" in lItem ? lItem["processPath"] : lItem["processName"])})
///Отправить запрос на формирование таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-planloglist",lResponseJSON[0]);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
},
dataType: "text"
});
}
///////////////////////////////
///Processor functions
///////////////////////////////
@ -507,32 +476,6 @@
dataType: "text"
});
}
mGlobal.Processor.LogListShow = function() {
lData = [
{
"Type":"GlobalDictKeyListValueGet",
"KeyList":["Processor","LogList"]
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-info-table-activitylogschedulelist",lResponseJSON["actionListResult"][0])
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
},
dataType: "text"
});
}
mGlobal.Server= {}
mGlobal.Server.JSONGet=function(inMethod, inURL, inDataJSON, inCallback)
{
@ -661,6 +604,37 @@
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
// Check user roles and update the Orchestrator UI
mGlobal.UserRoleUpdate=function() {
$.ajax({
type: "POST",
url: 'Orchestrator/UserRoleHierarchyGet',
data: "",
success:
function(lData,l2,l3)
{
var lResponseDict=JSON.parse(lData)
//Turn on the Lookmachine screenshot button
var lDict = ((lResponseDict["Orchestrator"] || {})["Controls"] || {}) // Get the Controls dict
if ("LookMachineScreenshots" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-control-lookmachinescreenshot").show() //Show button
}
//Turn on the restart orchestrator button
var lDict = ((lResponseDict["Orchestrator"] || {})["Controls"] || {}) // Get the Controls dict
if ("RestartOrchestrator" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-control-restartorchestrator").show() //Show button
}
//Turn on the rdp session list
var lDict = ((lResponseDict["Orchestrator"] || {})["RDPActive"] || {}) // Get the Controls dict
if ("ListRead" in lDict || Object.keys(lDict).length == 0) {
$(".openrpa-rdpactive-title").show() //Show section
$(".openrpa-robotrdpactive-control-panel-general").show() //Show section
}
},
dataType: "text"
});
}
mGlobal.UserRoleUpdate() // Cal the update User Roles function
})
;
</script>
@ -781,75 +755,20 @@
<h2 class="ui header inverted">...</h2>
</div>
<div class="nine wide column">
<h2 class="ui header inverted">Robot RDP active list</h2>
<h2 class="ui header inverted openrpa-rdpactive-title" style="display:none;">Robot RDP active list</h2>
</div>
</div>
<div class="row">
<div class="five wide column">
<button class="ui labeled icon button" onclick="mGlobal.Monitor.ScreenshotModal.Show();">
<button class="ui labeled icon button openrpa-control-lookmachinescreenshot" onclick="mGlobal.Monitor.ScreenshotModal.Show();" style="display: none;">
<i class="desktop icon"></i>
Look machine screenshot
</button>
<button class="ui labeled icon button red" onclick="mGlobal.Controller.OrchestratorRestart();">
<button class="ui labeled icon button red openrpa-control-restartorchestrator" onclick="mGlobal.Controller.OrchestratorRestart(); " style="display: none;>
<i class="redo icon"></i>
Restart Orchestrator
</button>
<button class="ui labeled icon button" onclick="mGlobal.Scheduler.ActivityTimeListShow();">
<i class="info icon"></i>
Scheduler activity time list
<script class="openrpa-hidden-info-table-planloglist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Time</th>
<th>Process path/Process name</th>
</tr>
</thead>
<tbody>
{{#Result}}
<tr>
<td>{{@index}}</td>
<td>{{TimeHH:MM}}{{TimeHH:MMStart}}</td>
<td>{{TimeHH:MMStop}}</td>
<td>{{Activity}}</td>
</tr>
{{/Result}}
</tbody>
</table>
</script>
</button>
<button class="ui labeled icon button" onclick="mGlobal.Processor.LogListShow();">
<i class="info icon"></i>
Processor logs
<script class="openrpa-hidden-info-table-activitylogschedulelist" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
<thead>
<tr>
<th>#</th>
<th>Activity type</th>
<th>Process</th>
<th>Activity DateTime plan</th>
<th>Activity DateTime fact</th>
</tr>
</thead>
<tbody>
{{#result}}
<tr>
<td>{{@index}}</td>
<td>{{activityType}}</td>
<td>{{processPath}}</td>
<td>{{activityDateTime}}</td>
<td class="negative
">{{activityStartDateTime}}</td>
</tr>
{{/result}}
</tbody>
</table>
</script>
</button>
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
<table class="ui celled table">
@ -927,7 +846,7 @@
</div>
<div class="two wide column">
</div>
<div class="nine wide column openrpa-robotrdpactive-control-panel-general">
<div class="nine wide column openrpa-robotrdpactive-control-panel-general" style="display:none;">
<div class="ui info message">
<button class="ui icon button labeled " onclick="mGlobal.RobotRDPActive.fControlPanelRefresh();">
<i class="sync alternate icon"></i>

@ -118,7 +118,15 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep
#Елемент на вход поступил - выполнить его анализ
else:
#Получить список элементов
lElementChildrenList=inElement.children()
lElementChildrenList = None
# 2020 06 10 Some times exception ctypes.ArgumentError is apper - set try except with wait
lFlagBool = True
while lFlagBool:
try:
lElementChildrenList = inElement.children()
lFlagBool = False # turn off the loop - all is ok
except ctypes.ArgumentError as e:
time.sleep(30) # error has come - go in sleep and retry
#Поступил index - точное добавление
if 'index' in inSpecificationList[0]:
if inSpecificationList[0]['index']<len(lElementChildrenList):
@ -444,7 +452,15 @@ def PWASpecification_Get_UIO(inControlSpecificationArray):
lTempObject=None
if len(inControlSpecificationArray) > 0:
#Сформировать выборку элементов, которые подходят под первый уровень спецификации
# 2020 06 10 Some times exception ctypes.ArgumentError is apper - set try except with wait
lSpecificationLvL1List = None
lFlagBool = True
while lFlagBool:
try:
lSpecificationLvL1List = pywinauto.findwindows.find_elements(**inControlSpecificationArray[0])
lFlagBool = False # turn off the loop - all is ok
except ctypes.ArgumentError as e:
time.sleep(30) # error has come - go in sleep and retry
for lItem in lSpecificationLvL1List:
#Сделать независимую копию и установить информацию о process_id и handle
lItemControlSpecificationArray=copy.deepcopy(inControlSpecificationArray)

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.7'
__version__ = 'v1.1.8'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs)
"""
__version__ = 'v1.1.7'
__version__ = 'v1.1.8'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot
Loading…
Cancel
Save