Nav apraksta

forparser.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import re
  2. import json
  3. fullexecution = {"type":"workflow","status":"FINISHED","start":"40447f30-fa44-4a4f-a133-4ee710368737","execution_argument":"","execution_id":"083eaa87-17ff-4aba-996c-83245051cf3d","execution_source":"default","workflow_id":"d7b73e8a-08fe-460e-987b-971cb6f1857f","last_node":"40447f30-fa44-4a4f-a133-4ee710368737","authorization":"b1264cd6-ed7a-4839-8caf-187eee8804b9","result":"TypeError: list indices must be integers or slices, not str","started_at":1593236788,"completed_at":1593236790,"project_id":"shuffle","locations":["europe-west2"],"workflow":{"actions":[{"app_name":"Testing","app_version":"1.0.0","app_id":"5411f573-9bba-44c4-a8d3-0e2bb704546d","errors":"null","id":"40447f30-fa44-4a4f-a133-4ee710368737","is_valid":True,"isStartNode":True,"sharing":True,"private_id":"","label":"Hello this is a name","small_image":"","large_image":"","environment":"Shuffle","name":"repeat_back_to_me","parameters":[{"description":"The message to repeat","id":"","name":"call","example":"REPEATING: Hello world","value":"$this is a test.name is not the same as $this is a test.name2 \n\n\nNot list $this is a test.loop.# either","multiline":True,"action_field":"","variant":"STATIC_VALUE","required":True,"schema":{"type":"string"}}],"execution_variable":{"description":"","id":"","name":"","value":""},"position":{"x":360.5,"y":454.5},"priority":0}],"branches":"null","triggers":"null","schedules":"null","configuration":{"exit_on_error":False,"start_from_top":False},"id":"d7b73e8a-08fe-460e-987b-971cb6f1857f","is_valid":True,"name":"App sdk parser testing","description":"","start":"40447f30-fa44-4a4f-a133-4ee710368737","owner":"43c36230-0a6e-40fc-aebc-a8ef57c81a88","sharing":"private","execution_org":{"name":"","org":"","users":"null","id":""},"workflow_variables":[{"description":"","id":"a034abee-5a5f-4347-9e58-6d2e58ce70f2","name":"This is a test","value":"[{\"data\": \"1.1.1.1\", \"data_type\": \"ip\"}]"}]},"results":[{"action":{"app_name":"Testing","app_version":"1.0.0","app_id":"5411f573-9bba-44c4-a8d3-0e2bb704546d","errors":"null","id":"40447f30-fa44-4a4f-a133-4ee710368737","is_valid":True,"isStartNode":True,"sharing":True,"private_id":"","label":"Hello this is a name","small_image":"","large_image":"","environment":"Shuffle","name":"repeat_back_to_me","parameters":[{"description":"The message to repeat","id":"","name":"call","example":"","value":"testing is not the same as testing2 \n\n\nNot list $this is a test.loop.# either","multiline":"false","action_field":"","variant":"STATIC_VALUE","required":True,"schema":{"type":"string"}}],"execution_variable":{"description":"","id":"","name":"","value":""},"position":{"x":360.5,"y":454.5},"priority":0},"execution_id":"083eaa87-17ff-4aba-996c-83245051cf3d","authorization":"b1264cd6-ed7a-4839-8caf-187eee8804b9","result":"TypeError: list indices must be integers or slices, not str","started_at":1593236790,"completed_at":1593236790,"status":"FAILURE"}]}
  4. # Takes a workflow execution as argument
  5. # Returns a string if the result is single, or a list if it's a list
  6. # Not implemented: lists
  7. multiexecutions = True
  8. def get_json_value(execution_data, input_data):
  9. parsersplit = input_data.split(".")
  10. actionname = parsersplit[0][1:].replace(" ", "_", -1)
  11. print(f"Actionname: {actionname}")
  12. # 1. Find the action
  13. baseresult = ""
  14. actionname_lower = actionname.lower()
  15. try:
  16. if actionname_lower == "exec":
  17. baseresult = execution_data["execution_argument"]
  18. else:
  19. for result in execution_data["results"]:
  20. resultlabel = result["action"]["label"].replace(" ", "_", -1).lower()
  21. if resultlabel.lower() == actionname_lower:
  22. baseresult = result["result"]
  23. break
  24. print("BEFORE VARIABLES!")
  25. if len(baseresult) == 0:
  26. try:
  27. #print("WF Variables: %s" % execution_data["workflow"]["workflow_variables"])
  28. for variable in execution_data["workflow"]["workflow_variables"]:
  29. variablename = variable["name"].replace(" ", "_", -1).lower()
  30. if variablename.lower() == actionname_lower:
  31. baseresult = variable["value"]
  32. break
  33. except KeyError as e:
  34. print("KeyError wf variables: %s" % e)
  35. pass
  36. except TypeError as e:
  37. print("TypeError wf variables: %s" % e)
  38. pass
  39. print("BEFORE EXECUTION VAR")
  40. if len(baseresult) == 0:
  41. try:
  42. #print("Execution Variables: %s" % execution_data["execution_variables"])
  43. for variable in execution_data["execution_variables"]:
  44. variablename = variable["name"].replace(" ", "_", -1).lower()
  45. if variablename.lower() == actionname_lower:
  46. baseresult = variable["value"]
  47. break
  48. except KeyError as e:
  49. print("KeyError exec variables: %s" % e)
  50. pass
  51. except TypeError as e:
  52. print("TypeError exec variables: %s" % e)
  53. pass
  54. except KeyError as error:
  55. print(f"KeyError in JSON: {error}")
  56. print(f"After first trycatch")
  57. # 2. Find the JSON data
  58. if len(baseresult) == 0:
  59. return ""
  60. if len(parsersplit) == 1:
  61. return baseresult
  62. baseresult = baseresult.replace("\'", "\"")
  63. basejson = {}
  64. try:
  65. basejson = json.loads(baseresult)
  66. except json.decoder.JSONDecodeError as e:
  67. return baseresult
  68. # This whole thing should be recursive.
  69. try:
  70. cnt = 0
  71. for value in parsersplit[1:]:
  72. cnt += 1
  73. print("VALUE: %s" % value)
  74. if value == "#":
  75. # FIXME - not recursive - should go deeper if there are more #
  76. print("HANDLE RECURSIVE LOOP OF %s" % basejson)
  77. returnlist = []
  78. try:
  79. for innervalue in basejson:
  80. print("Value: %s" % innervalue[parsersplit[cnt+1]])
  81. returnlist.append(innervalue[parsersplit[cnt+1]])
  82. except IndexError as e:
  83. print("Indexerror inner: %s" % e)
  84. # Basically means its a normal list, not a crazy one :)
  85. # Custom format for ${name[0,1,2,...]}$
  86. indexvalue = "${NO_SPLITTER%s}$" % json.dumps(basejson)
  87. if len(returnlist) > 0:
  88. indexvalue = "${NO_SPLITTER%s}$" % json.dumps(returnlist)
  89. print("INDEXVAL: ", indexvalue)
  90. return indexvalue
  91. except TypeError as e:
  92. print("TypeError inner: %s" % e)
  93. # Example format: ${[]}$
  94. parseditem = "${%s%s}$" % (parsersplit[cnt+1], json.dumps(returnlist))
  95. print("PARSED LOOP ITEM: %s" % parseditem)
  96. return parseditem
  97. else:
  98. print("BEFORE NORMAL VALUE: ", basejson, value)
  99. if len(value) == 0:
  100. return basejson
  101. if isinstance(basejson[value], str):
  102. print(f"LOADING STRING '%s' AS JSON" % basejson[value])
  103. try:
  104. basejson = json.loads(basejson[value])
  105. except json.decoder.JSONDecodeError as e:
  106. print("RETURNING BECAUSE '%s' IS A NORMAL STRING" % basejson[value])
  107. return basejson[value]
  108. else:
  109. basejson = basejson[value]
  110. except KeyError as e:
  111. print("Lower keyerror: %s" % e)
  112. return "KeyError: Couldn't find key: %s" % e
  113. return basejson
  114. parameter = {
  115. "value": """{
  116. "data8": "Not list $this is a test.#.data either with the items $this is a test.#.data_type"
  117. }"""
  118. }
  119. match = ".*?([$]{1}([a-zA-Z0-9 _-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,})"
  120. actualitem = re.findall(match, parameter["value"], re.MULTILINE)
  121. print("ACTUAL: ", actualitem)
  122. if len(actualitem) > 0:
  123. data = parameter["value"]
  124. counter = 0
  125. for replace in actualitem:
  126. try:
  127. to_be_replaced = replace[0]
  128. except IndexError:
  129. continue
  130. value = get_json_value(fullexecution, to_be_replaced)
  131. if isinstance(value, str):
  132. if "${" in value and "}$" in value:
  133. counter += 1
  134. parameter["value"] = parameter["value"].replace(to_be_replaced, value)
  135. elif isinstance(value, dict):
  136. parameter["value"] = parameter["value"].replace(to_be_replaced, json.dumps(value))
  137. elif isinstance(value, list):
  138. parameter["value"] = parameter["value"].replace(to_be_replaced, json.dumps(value))
  139. print(parameter["value"])
  140. submatch = "([${]{2}([0-9a-zA-Z_-]+)(\[.*\])[}$]{2})"
  141. actualitem = re.findall(submatch, parameter["value"], re.MULTILINE)
  142. print()
  143. # Kind of the same thing again, but different usage
  144. if len(actualitem) > 0:
  145. minlength = 0
  146. # 1. Find the length of the longest array
  147. # 2. Build an array with the base values based on parameter["value"]
  148. # 3. Get the n'th value of the generated list from values
  149. # 4. Execute all n answers
  150. replacements = {}
  151. for replace in actualitem:
  152. try:
  153. to_be_replaced = replace[0]
  154. actualitem = replace[2]
  155. except IndexError:
  156. continue
  157. itemlist = json.loads(actualitem)
  158. if len(itemlist) > minlength:
  159. minlength = len(itemlist)
  160. replacements[to_be_replaced] = actualitem
  161. resultarray = []
  162. for i in range(0, minlength):
  163. tmpitem = json.loads(json.dumps(parameter["value"]))
  164. for key, value in replacements.items():
  165. replacement = json.loads(value)[i]
  166. tmpitem = tmpitem.replace(key, replacement, -1)
  167. resultarray.append(tmpitem)
  168. # With this parameter ready, add it to... a greater list of parameters. Rofl
  169. print(resultarray[0])
  170. else:
  171. print("Normal execution")
  172. pass