diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
index ee45af62..c1fa9b19 100644
--- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
+++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py
@@ -1,6 +1,5 @@
import json, os
import copy
-from inspect import signature # For detect count of def args
from . import __Orchestrator__
#ControlPanelDict
from desktopmagic.screengrab_win32 import (
@@ -15,6 +14,7 @@ from .Web import Basic
from . import BackwardCompatibility # Support old up to 1.2.0 defs
from . import Processor
from . import SettingsTemplate
+
# # # # # # # # # # # #
# v 1.2.0 Functionallity
# # # # # # # # # # # #
@@ -380,6 +380,31 @@ def pyOpenRPA_Agent_O2A(inRequest, inGSettings):
except Exception as e:
if lL: lL.exception("pyOpenRPA_Agent_O2A Exception!")
lThisAgentDict["ConnectionCountInt"] -= 1 # Connection go to be closed - decrement the connection count
+
+def pyOpenRPA_Debugging_HelperDefList(inRequest, inGSettings):
+ # Parse query
+ lResultDict = {
+ "success": True,
+ "results": []
+ }
+ # Get the path
+ lPathSplitList = __Orchestrator__.WebRequestParsePath(inRequest=inRequest).split('/')
+ lQueryStr = None
+ if "HelperDefList" != lPathSplitList[-1] and "" != lPathSplitList[-1]: lQueryStr = lPathSplitList[-1]
+ lDefList = __Orchestrator__.ActivityItemHelperDefList(inDefQueryStr=lQueryStr)
+ for lDefStr in lDefList:
+ lResultDict["results"].append({"name": lDefStr, "value": lDefStr, "text": lDefStr})
+ __Orchestrator__.WebRequestResponseSend(inRequest=inRequest, inResponeStr=json.dumps(lResultDict))
+
+def pyOpenRPA_Debugging_HelperDefAutofill(inRequest, inGSettings):
+ # Parse query
+ # Get the path
+ lPathSplitList = __Orchestrator__.WebRequestParsePath(inRequest=inRequest).split('/')
+ lQueryStr = None
+ if "HelperDefAutofill" != lPathSplitList[-1] and "" != lPathSplitList[-1]: lQueryStr = lPathSplitList[-1]
+ lResultDict = __Orchestrator__.ActivityItemHelperDefAutofill(inDef = lQueryStr)
+ __Orchestrator__.WebRequestResponseSend(inRequest=inRequest, inResponeStr=json.dumps(lResultDict))
+
# See docs in Agent (pyOpenRPA.Agent.A2O)
def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lL = inGSettings["Logger"]
@@ -448,7 +473,8 @@ def SettingsUpdate(inGlobalConfiguration):
{"Method": "POST", "URL": "/pyOpenRPA/ProcessorQueueAdd", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Processor, "ResponseContentType": "application/json"},
{"Method": "POST", "URL": "/pyOpenRPA/ActivityListExecute", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ActivityListExecute, "ResponseContentType": "application/json"},
{"Method": "POST", "URL": "/pyOpenRPA/Agent/O2A", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_O2A, "ResponseContentType": "application/json"},
- {"Method": "POST", "URL": "/pyOpenRPA/Agent/A2O", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_A2O, "ResponseContentType": "application/json"},
+ {"Method": "GET", "URL": "/pyOpenRPA/Debugging/HelperDefList/", "MatchType": "BeginWith","ResponseDefRequestGlobal": pyOpenRPA_Debugging_HelperDefList, "ResponseContentType": "application/json"},
+ {"Method": "GET", "URL": "/pyOpenRPA/Debugging/HelperDefAutofill/", "MatchType": "BeginWith","ResponseDefRequestGlobal": pyOpenRPA_Debugging_HelperDefAutofill, "ResponseContentType": "application/json"},
]
inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList
return inGlobalConfiguration
\ No newline at end of file
diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.js b/Sources/pyOpenRPA/Orchestrator/Web/Index.js
index 018fdde0..ad17e3d3 100644
--- a/Sources/pyOpenRPA/Orchestrator/Web/Index.js
+++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.js
@@ -893,11 +893,43 @@ $(document).ready(function() {
mGlobal.pyOpenRPA.ServerLogListRefreshDef(); // Init the refresh data def from the log window
mGlobal.pyOpenRPA.ServerLogListDoRenderTrue(); // Init button to freeze/unfreeze textare with logs
- $('.ui.dropdown').dropdown();
+ //$('.ui.dropdown').dropdown();
////////////////////////////////////////////
- // Debugging
+ // 1.2.7 Debugging
/// Execute ActivityItem
+ // 1.2.7 Debugging toolbox init
+ $('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')
+ .dropdown({
+ apiSettings: {
+ // this url parses query server side and returns filtered results
+ url: '/pyOpenRPA/Debugging/HelperDefList/{query}'
+ },
+ })
+ ;
+ // Debugging onchange def autofill init
+ $('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')[0].onchange=function(inEvent){
+ lValueStr = inEvent.target.value
+ $.ajax({
+ type: "GET",
+ url: '/pyOpenRPA/Debugging/HelperDefAutofill/'+lValueStr,
+ data: null,
+ success:
+ function(lData,l2,l3)
+ {
+ var lResponseJSON=JSON.parse(lData)
+ console.log("HelperDefAutofill:")
+ console.log(lResponseJSON)
+ $(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value = JSON.stringify(lResponseJSON["ArgList"])
+ $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value = JSON.stringify(lResponseJSON["ArgDict"])
+ $(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value = JSON.stringify(lResponseJSON["ArgGSettingsStr"])
+ $(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value = JSON.stringify(lResponseJSON["ArgLoggerStr"])
+ },
+ dataType: "text"
+ });
+ }
+
+
mGlobal.pyOpenRPA.DebuggingExecute=function() {
///EXAMPLE
// {
@@ -910,14 +942,14 @@ $(document).ready(function() {
///Подготовить конфигурацию
lArgListStr = $(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value
lArgDictStr = $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value
- lArgGSettingsStr = $(".mGlobal-pyOpenRPA-Debugging-ArgGSettings")[0].value
- lArgLoggerStr = $(".mGlobal-pyOpenRPA-Debugging-ArgLogger")[0].value
+ lArgGSettingsStr = $(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value
+ lArgLoggerStr = $(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value
lActivityItem = {
"Def":$(".mGlobal-pyOpenRPA-Debugging-Def")[0].value, // def link or def alias (look gSettings["Processor"]["AliasDefDict"])
"ArgList":(lArgListStr == "" ? [] : JSON.parse(lArgListStr)), // Args list
"ArgDict":(lArgDictStr == "" ? {} : JSON.parse(lArgDictStr)), // Args dictionary
- "ArgGSettings": (lArgGSettingsStr == "" ? null : lArgGSettingsStr), // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
- "ArgLogger": (lArgLoggerStr == "" ? null : lArgLoggerStr) // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
+ "ArgGSettingsStr": (lArgGSettingsStr == "" ? null : lArgGSettingsStr), // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
+ "ArgLoggerStr": (lArgLoggerStr == "" ? null : lArgLoggerStr) // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
}
lData = [lActivityItem]
$.ajax({
diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
index c355bbd4..c74326e4 100644
--- a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
+++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml
@@ -304,11 +304,19 @@
Debugging - Send
-
-
- Def
-
-
+
+
Def
+
+
+
+
+
Def
+
+
Western Sahara
+
Yemen
+
Zambia
+
Zimbabwe
+
@@ -324,15 +332,15 @@
- ArgGSettings
+ ArgGSettingsStr
-
+
- ArgLogger
+ ArgLoggerStr
-
+
Execute
diff --git a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py
index 83b88f0c..b44dd0ab 100644
--- a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py
+++ b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py
@@ -1,6 +1,6 @@
import subprocess, json, psutil, time, os, win32security, sys, base64, logging, ctypes, copy #Get input argument
import pickle
-
+import inspect
from partd import Server
from . import Server
@@ -29,6 +29,7 @@ import uuid # Generate uuid
import datetime # datetime
import math
import glob # search the files
+import urllib
#Единый глобальный словарь (За основу взять из Settings.py)
gSettingsDict = None
@@ -874,6 +875,15 @@ def WebRequestParseBodyJSON(inRequest):
"""
return json.loads(WebRequestParseBodyStr(inRequest=inRequest))
+def WebRequestParsePath(inRequest):
+ """
+ Parse the request - extract the url. Example: /pyOpenRPA/Debugging/DefHelper/...
+
+ :param inRequest:
+ :return: Str, Example: /pyOpenRPA/Debugging/DefHelper/...
+ """
+ return urllib.parse.unquote(inRequest.path)
+
def WebRequestParseFile(inRequest):
"""
Parse the request - extract the file (name, body in bytes)
@@ -900,6 +910,13 @@ def WebRequestParseFile(inRequest):
return lResultTurple
+def WebRequestResponseSend(inRequest, inResponeStr):
+ """
+ Send response for the request
+ :return:
+ """
+ inRequest.OpenRPAResponseDict["Body"] = bytes(inResponeStr, "utf8")
+
def WebUserInfoGet(inRequest):
"""
Return User info about request
@@ -1109,6 +1126,7 @@ def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None):
"""
Create alias for def (can be used in ActivityItem in field Def)
!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment)
+ Deprecated. See ActivityItemDefAliasCreate
.. code-block:: python
@@ -1128,21 +1146,13 @@ def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None):
:param inAliasStr: String alias for associated def
:return: str Alias string (Alias can be regenerated if previous alias was occupied)
"""
- #TODO Pay attention - New alias can be used too - need to create more complex algorythm to create new alias!
- inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
- lL = inGSettings["Logger"]
- if inAliasStr is None: inAliasStr = str(inDef)
- # Check if key is not exists
- if inAliasStr in inGSettings["ProcessorDict"]["AliasDefDict"]:
- inAliasStr = str(inDef)
- if lL: lL.warning(f"Orchestrator.ProcessorAliasDefCreate: Alias {inAliasStr} already exists in alias dictionary. Another alias will be generated and returned")
- inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef
- return inAliasStr
+ return ActivityItemDefAliasCreate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings)
def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None):
"""
Update alias for def (can be used in ActivityItem in field Def).
!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment)
+ Deprecated. See ActivityItemDefAliasUpdate
.. code-block:: python
@@ -1162,12 +1172,58 @@ def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None):
:param inAliasStr: String alias for associated def
:return: str Alias string
"""
- inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
- if callable(inDef): inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef
- else: raise Exception(f"pyOpenRPA Exception: You can't use Orchestrator.ProcessorAliasDefUpdate with arg 'inDef' string value. inDef is '{inDef}', inAliasStr is '{inAliasStr}'")
- return inAliasStr
+ return ActivityItemDefAliasUpdate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings)
-def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False):
+# ActivityItem defs
+def ActivityItemHelperDefList(inDefQueryStr=None):
+ """
+ Create list of the available Def names in activity item. You can use query def filter via arg inDefQueryStr
+
+ :param inDefStr:
+ :return: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...]
+ """
+ lResultList = []
+ if inDefQueryStr is not None: # do search alg
+ for lKeyStr in GSettingsGet()["ProcessorDict"]["AliasDefDict"]:
+ if inDefQueryStr in lKeyStr:
+ lResultList.append(lKeyStr)
+ else:
+ for lKeyStr in GSettingsGet()["ProcessorDict"]["AliasDefDict"]:
+ lResultList.append(lKeyStr)
+ return lResultList
+
+def ActivityItemHelperDefAutofill(inDef):
+ """
+ Detect def by the name and prepare the activity item dict with values.
+
+ :param inDef:
+ :return:
+ """
+ lResultDict = {
+ "Def": None,
+ "ArgList": [],
+ "ArgDict": {},
+ "ArgGSettingsStr": None,
+ "ArgLoggerStr": None
+ }
+ lResultDict["Def"] = inDef
+ lGS = GSettingsGet()
+ lDefSignature = inspect.signature(lGS["ProcessorDict"]["AliasDefDict"][inDef])
+ for lItemKeyStr in lDefSignature.parameters:
+ lItemValue = lDefSignature.parameters[lItemKeyStr]
+ # Check if arg name contains "GSetting" or "Logger"
+ if "GSETTING" in lItemKeyStr.upper():
+ lResultDict["ArgGSettingsStr"] = lItemKeyStr
+ elif "LOGGER" in lItemKeyStr.upper():
+ lResultDict["ArgLoggerStr"] = lItemKeyStr
+ else:
+ if lItemValue.default is inspect._empty:
+ lResultDict["ArgDict"][lItemKeyStr] = None
+ else:
+ lResultDict["ArgDict"][lItemKeyStr] = lItemValue.default
+ return lResultDict
+
+def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False):
"""
Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute.
@@ -1179,7 +1235,7 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet
# EXAMPLE 1
def TestDef(inArg1Str, inGSettings, inLogger):
pass
- lActivityItem = Orchestrator.ProcessorActivityItemCreate(
+ lActivityItem = Orchestrator.ActivityItemCreate(
inDef = TestDef,
inArgList=[],
inArgDict={"inArg1Str": "ArgValueStr"},
@@ -1197,11 +1253,11 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet
# EXAMPLE 2
def TestDef(inArg1Str):
pass
- Orchestrator.ProcessorAliasDefUpdate(
+ Orchestrator.ActivityItemDefAliasUpdate(
inGSettings = gSettings,
inDef = TestDef,
inAliasStr="TestDefAlias")
- lActivityItem = Orchestrator.ProcessorActivityItemCreate(
+ lActivityItem = Orchestrator.ActivityItemCreate(
inDef = "TestDefAlias",
inArgList=[],
inArgDict={"inArg1Str": "ArgValueStr"},
@@ -1241,6 +1297,132 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet
}
return lActivityItemDict
+
+def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None):
+ """
+ Create alias for def (can be used in ActivityItem in field Def)
+ !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment)
+
+ .. code-block:: python
+
+ # USAGE
+ from pyOpenRPA import Orchestrator
+
+ def TestDef():
+ pass
+ lAliasStr = Orchestrator.ActivityItemDefAliasCreate(
+ inGSettings = gSettings,
+ inDef = TestDef,
+ inAliasStr="TestDefAlias")
+ # Now you can call TestDef by the alias from var lAliasStr with help of ActivityItem (key Def = lAliasStr)
+
+ :param inGSettings: Global settings dict (singleton)
+ :param inDef: Def
+ :param inAliasStr: String alias for associated def
+ :return: str Alias string (Alias can be regenerated if previous alias was occupied)
+ """
+ #TODO Pay attention - New alias can be used too - need to create more complex algorythm to create new alias!
+ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
+ lL = inGSettings["Logger"]
+ if inAliasStr is None: inAliasStr = str(inDef)
+ # Check if key is not exists
+ if inAliasStr in inGSettings["ProcessorDict"]["AliasDefDict"]:
+ inAliasStr = str(inDef)
+ if lL: lL.warning(f"Orchestrator.ProcessorAliasDefCreate: Alias {inAliasStr} already exists in alias dictionary. Another alias will be generated and returned")
+ inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef
+ return inAliasStr
+
+def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None):
+ """
+ Update alias for def (can be used in ActivityItem in field Def).
+ !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment)
+
+ .. code-block:: python
+
+ # USAGE
+ from pyOpenRPA import Orchestrator
+
+ def TestDef():
+ pass
+ Orchestrator.ActivityItemDefAliasUpdate(
+ inGSettings = gSettings,
+ inDef = TestDef,
+ inAliasStr="TestDefAlias")
+ # Now you can call TestDef by the alias "TestDefAlias" with help of ActivityItem (key Def = "TestDefAlias")
+
+ :param inGSettings: Global settings dict (singleton)
+ :param inDef: Def
+ :param inAliasStr: String alias for associated def
+ :return: str Alias string
+ """
+ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
+ if callable(inDef): inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef
+ else: raise Exception(f"pyOpenRPA Exception: You can't use Orchestrator.ActivityItemDefAliasUpdate with arg 'inDef' string value. inDef is '{inDef}', inAliasStr is '{inAliasStr}'")
+ return inAliasStr
+
+
+
+def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False):
+ """
+ Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute.
+ Deprecated. See ActivityItemCreate
+ .. code-block:: python
+
+ # USAGE
+ from pyOpenRPA import Orchestrator
+
+ # EXAMPLE 1
+ def TestDef(inArg1Str, inGSettings, inLogger):
+ pass
+ lActivityItem = Orchestrator.ProcessorActivityItemCreate(
+ inDef = TestDef,
+ inArgList=[],
+ inArgDict={"inArg1Str": "ArgValueStr"},
+ inArgGSettingsStr = "inGSettings",
+ inArgLoggerStr = "inLogger")
+ # lActivityItem:
+ # {
+ # "Def":TestDef,
+ # "ArgList":inArgList,
+ # "ArgDict":inArgDict,
+ # "ArgGSettings": "inArgGSettings",
+ # "ArgLogger": "inLogger"
+ # }
+
+ # EXAMPLE 2
+ def TestDef(inArg1Str):
+ pass
+ Orchestrator.ProcessorAliasDefUpdate(
+ inGSettings = gSettings,
+ inDef = TestDef,
+ inAliasStr="TestDefAlias")
+ lActivityItem = Orchestrator.ProcessorActivityItemCreate(
+ inDef = "TestDefAlias",
+ inArgList=[],
+ inArgDict={"inArg1Str": "ArgValueStr"},
+ inArgGSettingsStr = None,
+ inArgLoggerStr = None)
+ # lActivityItem:
+ # {
+ # "Def":"TestDefAlias",
+ # "ArgList":inArgList,
+ # "ArgDict":inArgDict,
+ # "ArgGSettings": None,
+ # "ArgLogger": None
+ # }
+
+ :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"])
+ :param inArgList: Args list for the Def
+ :param inArgDict: Args dict for the def
+ :param inArgGSettingsStr: Name of def argument of the GSettings dict
+ :param inArgLoggerStr: Name of def argument of the logging object
+ :param inGUIDStr: GUID which you can specify. If None the GUID will be generated
+ :param inThreadBool: True - execute ActivityItem in new thread; False - in processor thread
+ :return: {}
+ """
+ return ActivityItemCreate(inDef=inDef, inArgList=inArgList, inArgDict=inArgDict, inArgGSettingsStr=inArgGSettingsStr, inArgLoggerStr=inArgLoggerStr,
+ inGUIDStr=inGUIDStr, inThreadBool=inThreadBool)
+
def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inActivityItemDict=None):
"""
Create and add activity item in processor queue.