From f1f706bca173f36b4db53a8f058a5e496d018010 Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Sat, 12 Dec 2020 21:55:34 +0300 Subject: [PATCH] - def UACKeyListCheck(inRequest, inRoleKeyList): #Check is client is has access for the key list - def WebUserInfoGet(inRequest): # Return User info about request Return {"DomainUpperStr":"", "UserNameUpperStr": ""} - def WebUserUACHierarchyGet(inRequest): # Return User UAC Hierarchy DICT Return {...} - Scheduler - Refactoring in gSettings (Scheduler > SchedulerDict) - def SchedulerActivityTimeAddWeekly(inGSettings, inTimeHHMMStr="23:55:", inWeekdayList=[], inActivityList=[]): # Add activity in time weekly - Scheduler now listen SchedulerDict - def ProcessorActivityItemAppend(inGSettings, inDef, inArgList=[], inArgDict={}, inArgGSettingsStr=None, inArgLoggerStr=None): # Add Activity item in Processor list --- Orchestrator/ControlPanel/CP_Test.py | 2 +- Orchestrator/OrchestratorSettings.py | 6 +- .../Orchestrator/BackwardCompatibility.py | 17 +- .../pyOpenRPA/Orchestrator/Orchestrator.py | 202 +++++++++++------- Sources/pyOpenRPA/Orchestrator/Processor.py | 59 ++--- .../Orchestrator/SettingsTemplate.py | 58 ++--- changelog.md | 17 +- 7 files changed, 206 insertions(+), 155 deletions(-) diff --git a/Orchestrator/ControlPanel/CP_Test.py b/Orchestrator/ControlPanel/CP_Test.py index 6c3c893e..01c7e402 100644 --- a/Orchestrator/ControlPanel/CP_Test.py +++ b/Orchestrator/ControlPanel/CP_Test.py @@ -48,5 +48,5 @@ def JSInitGenerator(): #Orchestrator settings def SettingsUpdate(inGSettings): # New way to add CP defs in orchestrator - no gSettings.. - Orchestrator.OrchestratorWebCPUpdate(inGSettings=inGSettings,inCPKeyStr="TEST",inHTMLRenderDef=CPRender, inJSONGeneratorDef=JSONGenerator, inJSInitGeneratorDef=JSInitGenerator) + Orchestrator.WebCPUpdate(inGSettings=inGSettings, inCPKeyStr="TEST", inHTMLRenderDef=CPRender, inJSONGeneratorDef=JSONGenerator, inJSInitGeneratorDef=JSInitGenerator) return inGSettings \ No newline at end of file diff --git a/Orchestrator/OrchestratorSettings.py b/Orchestrator/OrchestratorSettings.py index 5f849d74..19c4e1b3 100644 --- a/Orchestrator/OrchestratorSettings.py +++ b/Orchestrator/OrchestratorSettings.py @@ -42,11 +42,11 @@ if __name__ == "__main__": # New init way - allow run as module -m PyOpenRPA.Orc #lUACClientDict["pyOpenRPADict"]["CPKeyDict"]["VersionCheck"]=True #lUACClientDict["pyOpenRPADict"]["CPKeyDict"]["TEST"]=True #lUACClientDict["pyOpenRPADict"]["AgentKeyDict"]["DESKTOP----;ND"]=True - Orchestrator.OrchestratorUACUpdate(inGSettings=gSettings, inADLoginStr="ND", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict) + Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="ND", inADStr="", inADIsDefaultBool=True, inURLList=[], inRoleHierarchyAllowedDict=lUACClientDict) # TEST Add User IMaslov - Add Login IMaslov to superuser of the Orchestrator - Orchestrator.OrchestratorUACUpdate(inGSettings=gSettings, inADLoginStr="IMaslov", inADStr="", inADIsDefaultBool=True, inURLList=[]) + Orchestrator.UACUpdate(inGSettings=gSettings, inADLoginStr="IMaslov", inADStr="", inADIsDefaultBool=True, inURLList=[]) # TEST Add Supertoken for the all access between robots - Orchestrator.OrchestratorUACSuperTokenUpdate(inGSettings=gSettings, inSuperTokenStr="1992-04-03-0643-ru-b4ff-openrpa52zzz") + Orchestrator.UACSuperTokenUpdate(inGSettings=gSettings, inSuperTokenStr="1992-04-03-0643-ru-b4ff-openrpa52zzz") ## !!! For Relative import !!! CP Version Check sys.path.insert(0,os.path.abspath(os.path.join(r""))) diff --git a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py index 64f123dd..36198815 100644 --- a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py +++ b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py @@ -389,5 +389,18 @@ def Update(inGSettings): if "CPDict" not in inGSettings: inGSettings["CPDict"]={} for lItemDict in inGSettings["ControlPanelDict"]["RobotList"]: inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None} - # Remove old structure ControlPanel - del inGSettings["ControlPanelDict"] \ No newline at end of file + # Remove old structure ControlPanel + del inGSettings["ControlPanelDict"] + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility + # Check if Scheduler is active > convert to SchedulerDict + if "Scheduler" in inGSettings: + if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]} + if "ActivityTimeCheckLoopSeconds" in inGSettings["Scheduler"]: + inGSettings["SchedulerDict"]["CheckIntervalSecFloat"] = inGSettings["Scheduler"]["ActivityTimeCheckLoopSeconds"] + for lItemDict in inGSettings["Scheduler"]["ActivityTimeList"]: + lItemDict["ActivityList"]=[v1_2_0_ProcessorOld2NewActivityDict(inActivityOld=lItemDict["Activity"])] + del lItemDict["Activity"] + inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) + # Remove old structure Scheduler + del inGSettings["Scheduler"] + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Scheduler to SchedulerDict with new features") # Log about compatibility diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py index 7de222fd..7130e478 100644 --- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py +++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py @@ -161,8 +161,15 @@ def OrchestratorSessionSave(inGSettings=None): ## Orchestrator session save if lL: lL.info( f"Orchestrator has dump the RDP list before the restart. The RDP List is {inGSettings['RobotRDPActive']['RDPList']}") return True + +#Check is client is has access for the key list +def UACKeyListCheck(inRequest, inRoleKeyList): + return inRequest.UACClientCheck(inRoleKeyList=inRoleKeyList) + + + # Update user access -def OrchestratorUACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[], inRoleHierarchyAllowedDict={}): +def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[], inRoleHierarchyAllowedDict={}): lUserTurple = (inADStr.upper(),inADLoginStr.upper()) # Create turple key for inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"] if inURLList==[] and lUserTurple not in inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"]: # Backward compatibility if user is not exist inURLList=[ @@ -198,16 +205,19 @@ def OrchestratorUACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBo inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({("",inADLoginStr.upper()):lRuleDomainUserDict}) # Add supertoken for the all access (it is need for the robot communication without human) -def OrchestratorUACSuperTokenUpdate(inGSettings, inSuperTokenStr): +def UACSuperTokenUpdate(inGSettings, inSuperTokenStr): lLoginStr = "SUPERTOKEN" - OrchestratorUACUpdate(inGSettings=inGSettings, inADLoginStr=lLoginStr) + UACUpdate(inGSettings=inGSettings, inADLoginStr=lLoginStr) inGSettings["Server"]["AccessUsers"]["AuthTokensDict"].update( {inSuperTokenStr:{"User":lLoginStr, "Domain":"", "TokenDatetime": datetime.datetime.now(), "FlagDoNotExpire":True}} ) -# OrchestratorWEB +# # # # # # # # # # # # # # # # # # # # # # # +# OrchestratorWeb defs +# # # # # # # # # # # # # # # # # # # # # # # + # Add control panel HTML, JSON generator or JS when page init -def OrchestratorWebCPUpdate(inGSettings, inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None): +def WebCPUpdate(inGSettings, inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None): # Create Struct if the re is current key if inCPKeyStr not in inGSettings["CPDict"]: inGSettings["CPDict"][inCPKeyStr] = {"HTMLRenderDef": None,"JSONGeneratorDef": None, "JSInitGeneratorDef": None} @@ -221,6 +231,16 @@ def OrchestratorWebCPUpdate(inGSettings, inCPKeyStr, inHTMLRenderDef=None, inJSO if inJSInitGeneratorDef is not None: inGSettings["CPDict"][inCPKeyStr]["JSInitGeneratorDef"] = inJSInitGeneratorDef +# Return User info about request Return {"DomainUpperStr":"", "UserNameUpperStr": ""} +def WebUserInfoGet(inRequest): + lDomainUpperStr = inRequest.OpenRPA["Domain"].upper() + lUserUpperStr = inRequest.OpenRPA["User"].upper() + return {"DomainUpperStr": lDomainUpperStr, "UserNameUpperStr": lUserUpperStr} + +# Return User UAC Hierarchy DICT Return {...} +def WebUserUACHierarchyGet(inRequest): + return inRequest.UserRoleHierarchyGet() + ## GSettings defs def GSettingsKeyListValueSet(inGSettings, inValue, inKeyList=[]): # Set value in GSettings by the key list lDict = inGSettings @@ -269,6 +289,19 @@ def GSettingsKeyListValueOperatorPlus(inGSettings, inValue, inKeyList=[]): # Ope lDict[inKeyList[-1]] += inValue #Set value return True +# Add Activity item in Processor list +def ProcessorActivityItemAppend(inGSettings, inDef, inArgList=[], inArgDict={}, inArgGSettingsStr=None, inArgLoggerStr=None): + lActivityList=[ + { + "Def":inDef, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":inArgList, # Args list + "ArgDict":inArgDict, # Args dictionary + "ArgGSettings": inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": inArgLoggerStr # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + }, + ] + inGSettings["ProcessorDict"]["ActivityList"]+=lActivityList + ## Process defs def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started ''' @@ -356,8 +389,22 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=[], inArgDict={}, inLog except Exception as e: if inLogger: inLogger.exception("Loop activity error: module/function not founded") +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Scheduler +# # # # # # # # # # # # # # # # # # # # # # # + +# Add activity in time weekly +def SchedulerActivityTimeAddWeekly(inGSettings, inTimeHHMMStr="23:55:", inWeekdayList=[], inActivityList=[]): + lActivityTimeItemDict = { + "TimeHH:MMStr": inTimeHHMMStr, # Time [HH:MM] to trigger activity + "WeekdayList": inWeekdayList, # List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] + "ActivityList": inActivityList, + "GUID": None # # Will be filled in Orchestrator automatically - is needed for detect activity completion + }, + inGSettings["SchedulerDict"]["ActivityTimeList"].append(lActivityTimeItemDict) + # # # # # # # # # # # # # # # # # # # # # # # # RDPSession # # # # # # # # # # # # # # # # # # # # # # # @@ -698,7 +745,7 @@ def Orchestrator(inGSettings): if lL: lL.warning(f"RDP Session List was restored from previous Orchestrator session") #Инициализация настроечных параметров - lDaemonLoopSeconds=gSettingsDict["Scheduler"]["ActivityTimeCheckLoopSeconds"] + lDaemonLoopSeconds=gSettingsDict["SchedulerDict"]["CheckIntervalSecFloat"] lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) lDaemonLastDateTime=datetime.datetime.now() gSettingsDict["Server"]["WorkingDirectoryPathStr"] = os.getcwd() # Set working directory in g settings @@ -762,74 +809,81 @@ def Orchestrator(inGSettings): gDaemonActivityLogDictRefreshSecInt = 10 # The second period for clear lDaemonActivityLogDict from old items gDaemonActivityLogDictLastTime = time.time() # The second perioad for clean lDaemonActivityLogDict from old items while True: - lCurrentDateTime = datetime.datetime.now() - #Циклический обход правил - lFlagSearchActivityType=True - # Periodically clear the lDaemonActivityLogDict - if time.time()-gDaemonActivityLogDictLastTime>=gDaemonActivityLogDictRefreshSecInt: - gDaemonActivityLogDictLastTime = time.time() # Update the time - for lIndex, lItem in enumerate(lDaemonActivityLogDict): - if lItem["ActivityEndDateTime"] and lCurrentDateTime<=lItem["ActivityEndDateTime"]: - pass - # Activity is actual - do not delete now - else: - # remove the activity - not actual - lDaemonActivityLogDict.pop(lIndex,None) - lIterationLastDateTime = lDaemonLastDateTime # Get current datetime before iterator (need for iterate all activities in loop) - # Iterate throught the activity list - for lIndex, lItem in enumerate(gSettingsDict["Scheduler"]["ActivityTimeList"]): - # Prepare GUID of the activity - lGUID = None - if "GUID" in lItem and lItem["GUID"]: - lGUID = lItem["GUID"] - else: - lGUID = str(uuid.uuid4()) - lItem["GUID"]=lGUID - - #Проверка дней недели, в рамках которых можно запускать активность - lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6]) - if lCurrentDateTime.weekday() in lItemWeekdayList: - if lFlagSearchActivityType: - ####################################################################### - #Branch 1 - if has TimeHH:MM - ####################################################################### - if "TimeHH:MM" in lItem: - #Вид активности - запуск процесса - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MM"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lActivityDateTime>=lDaemonLastDateTime and - lCurrentDateTime>=lActivityDateTime): - # Log info about activity - if lL: lL.info(f"Scheduler:: Activity is started. Scheduler item: {lItem}") #Logging - # Do the activity - Processor.ActivityListOrDict(lItem["Activity"]) - lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity - ####################################################################### - #Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds - ####################################################################### - if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem: - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M") - lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lCurrentDateTime=lActivityDateTime and - (lGUID,lActivityDateTime) not in lDaemonActivityLogDict): - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime} - #Запуск циклической процедуры - Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"]) - lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity - #Уснуть до следующего прогона - time.sleep(lDaemonLoopSeconds) + try: + lCurrentDateTime = datetime.datetime.now() + #Циклический обход правил + lFlagSearchActivityType=True + # Periodically clear the lDaemonActivityLogDict + if time.time()-gDaemonActivityLogDictLastTime>=gDaemonActivityLogDictRefreshSecInt: + gDaemonActivityLogDictLastTime = time.time() # Update the time + for lIndex, lItem in enumerate(lDaemonActivityLogDict): + if lItem["ActivityEndDateTime"] and lCurrentDateTime<=lItem["ActivityEndDateTime"]: + pass + # Activity is actual - do not delete now + else: + # remove the activity - not actual + lDaemonActivityLogDict.pop(lIndex,None) + lIterationLastDateTime = lDaemonLastDateTime # Get current datetime before iterator (need for iterate all activities in loop) + # Iterate throught the activity list + for lIndex, lItem in enumerate(gSettingsDict["SchedulerDict"]["ActivityTimeList"]): + try: + # Prepare GUID of the activity + lGUID = None + if "GUID" in lItem and lItem["GUID"]: + lGUID = lItem["GUID"] + else: + lGUID = str(uuid.uuid4()) + lItem["GUID"]=lGUID + + #Проверка дней недели, в рамках которых можно запускать активность + lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6]) + if lCurrentDateTime.weekday() in lItemWeekdayList: + if lFlagSearchActivityType: + ####################################################################### + #Branch 1 - if has TimeHH:MM + ####################################################################### + if "TimeHH:MM" in lItem: + #Вид активности - запуск процесса + #Сформировать временной штамп, относительно которого надо будет проверять время + #часовой пояс пока не учитываем + lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MM"],"%H:%M") + lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) + #Убедиться в том, что время наступило + if ( + lActivityDateTime>=lDaemonLastDateTime and + lCurrentDateTime>=lActivityDateTime): + # Log info about activity + if lL: lL.info(f"Scheduler:: Activity list is started in new thread. Scheduler item: {lItem}") #Logging + # Do the activity + lThread = threading.Thread(target=Processor.ActivityListExecute, kwargs={"inGSettings": inGSettings, "inActivityList":lItem["ActivityList"]}) + lThread.start() + lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity + ####################################################################### + #Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds + ####################################################################### + if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem: + #Сформировать временной штамп, относительно которого надо будет проверять время + #часовой пояс пока не учитываем + lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M") + lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) + lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M") + lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) + #Убедиться в том, что время наступило + if ( + lCurrentDateTime=lActivityDateTime and + (lGUID,lActivityDateTime) not in lDaemonActivityLogDict): + #Запись в массив отработанных активностей + lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime} + #Запуск циклической процедуры + Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"]) + except Exception as e: + if lL: lL.exception(f"Scheduler: Exception has been catched in Scheduler module when activity time item was initialising. ActivityTimeItem is {lItem}") + lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity + #Уснуть до следующего прогона + time.sleep(lDaemonLoopSeconds) + except Exception as e: + if lL: lL.exception(f"Scheduler: Exception has been catched in Scheduler module. Global error") # Backward compatibility below to 1.2.0 def __deprecated_orchestrator_start__(): diff --git a/Sources/pyOpenRPA/Orchestrator/Processor.py b/Sources/pyOpenRPA/Orchestrator/Processor.py index 512a5280..f1984714 100644 --- a/Sources/pyOpenRPA/Orchestrator/Processor.py +++ b/Sources/pyOpenRPA/Orchestrator/Processor.py @@ -32,33 +32,36 @@ def ProcessorRunSync(inGSettings): def ActivityListExecute(inGSettings, inActivityList): lL = inGSettings["Logger"] # Logger alias lResultList = [] # init the result list - for lActivityItem in inActivityList: # Iterate throught the activity list - lDef = None # Def variable - if callable(lActivityItem["Def"]): # CHeck if def is callable - lDef = lActivityItem["Def"] # Get the def - else: # Is not callable - check alias - lDef = inGSettings["ProcessorDict"]["AliasDefDict"].get(lActivityItem["Def"], None) # get def if def key in Alias def storage - #gSettings - lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) - # # Prepare arg dict - gSettings - if type(lGSettingsDictKey) is str: # check if gSetting key is in ArgDict - lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict - # # Prepare arg list - elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict - lActivityItem["ArgList"].insert(lGSettingsDictKey,inGSettings)# Set the gSettings in list by the index - #Logger - lLoggerDictKey = lActivityItem.pop("ArgLogger",None) - # # Prepare arg dict - gSettings - if type(lLoggerDictKey) is str: # check if gSetting key is in ArgDict - lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict - # # Prepare arg list - elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict - lActivityItem["ArgList"].insert(lLoggerDictKey,lL)# Set the lLogger in list by the index + try: + for lActivityItem in inActivityList: # Iterate throught the activity list + lDef = None # Def variable + if callable(lActivityItem["Def"]): # CHeck if def is callable + lDef = lActivityItem["Def"] # Get the def + else: # Is not callable - check alias + lDef = inGSettings["ProcessorDict"]["AliasDefDict"].get(lActivityItem["Def"], None) # get def if def key in Alias def storage + #gSettings + lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) + # # Prepare arg dict - gSettings + if type(lGSettingsDictKey) is str: # check if gSetting key is in ArgDict + lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict + # # Prepare arg list + elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict + lActivityItem["ArgList"].insert(lGSettingsDictKey,inGSettings)# Set the gSettings in list by the index + #Logger + lLoggerDictKey = lActivityItem.pop("ArgLogger",None) + # # Prepare arg dict - gSettings + if type(lLoggerDictKey) is str: # check if gSetting key is in ArgDict + lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict + # # Prepare arg list + elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict + lActivityItem["ArgList"].insert(lLoggerDictKey,lL)# Set the lLogger in list by the index - try: # try to run function from Processor.py - lActivityItemResult = lDef(*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) - lResultList.append(lActivityItemResult) # return the result - except Exception as e: - if lL: lL.exception(f"Processor.ActivityListExecute: Exception in def execution - activity will be ignored. Activity item: {lActivityItem}") # Logging - lResultList.append(e) # return the generated exception + try: # try to run function from Processor.py + lActivityItemResult = lDef(*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) + lResultList.append(lActivityItemResult) # return the result + except Exception as e: + if lL: lL.exception(f"Processor.ActivityListExecute: Exception in def execution - activity will be ignored. Activity item: {lActivityItem}") # Logging + lResultList.append(e) # return the generated exception + except Exception as e: + if lL: lL.exception(f"Processor.ActivityListExecute: Exception when initialisation - All activity list will be ignored. Activity list: {inActivityList}") # Logging return lResultList # return the result list \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py index fcd94d06..e0584b76 100644 --- a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py +++ b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py @@ -155,50 +155,22 @@ def __Create__(): # }, ] }, - "Scheduler": { - "ActivityTimeCheckLoopSeconds": 5, # Количество секунд, между циклами проверки действий + "SchedulerDict": { + "CheckIntervalSecFloat": 5.0, # Check interval in seconds "ActivityTimeList": [ - #{ - # "TimeHH:MM": "22:23", # Time [HH:MM] to trigger activity - # "WeekdayList": [1, 2, 3, 4, 5, 6, 7], - # # List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] - # "Activity": { - # "Type": "ProcessStart", # Activity type - # "Path": "start", # Executable file path - # "ArgList": ["cmd.exe", "/c", "PIPUpgrade.cmd"] # List of the arguments - # }, - # "GUID": None - # # Will be fied in Orchestrator automatically - is needed for detect activity completion - #}, - #{ - # "TimeHH:MM": "19:20", # Time [HH:MM] to trigger activity - # "WeekdayList": [1, 2, 3], - # # List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] - # "Activity": { - # "Type": "ProcessStop", # Activity type - # "Name": "OpenRPARobotDaemon.exe", # Process name - # "FlagForce": True, # Force process close - # "User": "%username%" # Empty, user or %username% - # }, - # "GUID": None - # # Will be fied in Orchestrator automatically - is needed for detect activity completion - #}, - #{ - # "TimeHH:MMStart": "12:40", # Time [HH:MM] to trigger activity - # "TimeHH:MMStop": "12:40", - # "ActivityIntervalSeconds": 2, - # "WeekdayList": [1, 2, 3, 4, 5, 6, 7], - # # List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] - # "Activity": { - # "Type": "ProcessStartIfTurnedOff", # Activity type - # "CheckTaskName": "notepad.exe", # Python function module name - # "Path": "notepad", # Python function name - # "ArgList": [] # Input python function args - # }, - # "GUID": None - # # Will be fied in Orchestrator automatically - is needed for detect activity completion - #} - ] + # { + # "TimeHH:MMStr": "22:23", # Time [HH:MM] to trigger activity + # "WeekdayList": [0, 1, 2, 3, 4, 5, 6], #List of the weekday index when activity is applicable, Default [0,1,2,3,4,5,6] + # "ActivityList": [ + # { + # "Type": "ProcessStart", # Activity type + # "Path": "start", # Executable file path + # "ArgList": ["cmd.exe", "/c", "PIPUpgrade.cmd"] # List of the arguments + # } + # ], + # "GUID": None # Will be filled in Orchestrator automatically - is needed for detect activity completion + # }, + ], }, "ProcessorDict": { # Has been changed. New general processor (one threaded) v.1.2.0 "ActivityList": [ # List of the activities diff --git a/changelog.md b/changelog.md index a57b1cab..c2c82f6d 100644 --- a/changelog.md +++ b/changelog.md @@ -28,8 +28,8 @@ - Add front autorefresh if front/back pyOpenRPA versions are differs (see CP_VersionCheck.py) - Add absolute/relative import for the control panels - Add new Orchestrator defs: -- - def OrchestratorUACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[]): - Update user access -- - def OrchestratorUACSuperTokenUpdate(inGSettings, inSuperTokenStr): # Add supertoken for the all access (it is need for the robot communication without human) +- - def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[]): - Update user access +- - def UACSuperTokenUpdate(inGSettings, inSuperTokenStr): # Add supertoken for the all access (it is need for the robot communication without human) - Create Web HTML / JS generators [pyOpenRPA.Orchestrator.Web.Basic] - - def JSEscapeForHTMLInline(inJSStr): # Escape JS to the safe JS for the inline JS in HTML tags ATTENTION! Use it only if want to paste JS into HTML tag - not in