kemi_mock.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #!/usr/bin/python3
  2. #parses the output of /usr/sbin/kamctl rpc app_python.api_list
  3. #
  4. #usage ./kemi_mock.py api.json > KSR.py
  5. #or for python 3.2
  6. #./kemi_mock.py api.json --no-union > KSR.py
  7. import json
  8. import sys
  9. from collections import defaultdict
  10. #python 3.2 doesnt support types.Union
  11. noUnion = False
  12. reserved_keywords = {"async"}
  13. def printMocReturn(module_name, func, indent):
  14. param_names = []
  15. param_list = []
  16. param_signature = ""
  17. if func['params'] is not None and func['params'] != 'none':
  18. param_list = func['params'].split(", ")
  19. i = 0
  20. for _ in param_list:
  21. param_names.append("param"+str(i))
  22. i = i + 1
  23. param_signature = ", ".join(param_names)
  24. prefix = ""
  25. for i in range(indent):
  26. prefix = prefix+"\t"
  27. print(prefix + "if \""+func['name']+"\" not in _mock_data['"+module_name+"']:")
  28. printDefaultReturn(func, indent+1)
  29. print(prefix + "node = _mock_data['"+module_name+"']['"+func['name']+"']")
  30. print(prefix + "if isinstance(node, types.FunctionType):")
  31. print(prefix + "\treturn node("+param_signature+")")
  32. for param in param_names:
  33. print(prefix + "if not isinstance(node, dict):")
  34. print(prefix + "\treturn node")
  35. print(prefix + "if str(" + param + ") in node:")
  36. print(prefix + "\tnode = node[str("+param+")]")
  37. print(prefix + "else:")
  38. printDefaultReturn(func, indent+1)
  39. print(prefix + "return node")
  40. def printDefaultReturn(func, indent):
  41. prefix = ""
  42. for i in range(indent):
  43. prefix = prefix+"\t"
  44. if func['ret'] == "bool":
  45. print(prefix + "return True")
  46. elif func['ret'] == "int":
  47. print(prefix + "return 1")
  48. elif func['ret'] == "str":
  49. print(prefix + "return \"\"")
  50. elif func['ret'] == "xval":
  51. print(prefix + "return None")
  52. else:
  53. print(prefix + "return")
  54. def printFunction(module_name, func, indent):
  55. params = ""
  56. log_params = ""
  57. if module_name == "":
  58. log_params = "\"" + func['name'] + "\""
  59. else:
  60. log_params = "\"" + module_name + "." + func['name'] + "\""
  61. log_format_params = "%s"
  62. param_list = []
  63. if func['params'] is not None and func['params'] != "none":
  64. param_list = func['params'].split(", ")
  65. i = 0
  66. for _ in param_list:
  67. if params != "":
  68. params = params + ", "
  69. params = params + "param" + str(i) + ": " + param_list[i]
  70. log_params = log_params + ", param" + str(i)
  71. log_format_params = log_format_params + ", %s"
  72. i = i+1
  73. if len(param_list) > 0:
  74. log_params = "(" + log_params + ")"
  75. prefix = ""
  76. for i in range(indent):
  77. prefix = prefix+"\t"
  78. if indent > 0:
  79. print(prefix + "@staticmethod")
  80. if func['ret'] == "bool":
  81. print(prefix + "def " + func['name'] +"("+params+") -> bool:")
  82. elif func['ret'] == "int":
  83. print(prefix + "def " + func['name'] +"("+params+") -> int:")
  84. elif func['ret'] == "str":
  85. print(prefix + "def " + func['name'] + "(" + params + ") -> int:")
  86. elif func['ret'] == "xval":
  87. if noUnion:
  88. print(prefix + "def " + func['name'] + "(" + params + "):")
  89. else:
  90. print(prefix + "def " + func['name'] +"("+params+") -> Union[int, str, None]:")
  91. else:
  92. print(prefix + "def " + func['name'] +"("+params+"):")
  93. generate_function_doc(module_name, func, prefix)
  94. print(prefix + "\tprint(\"Calling " + log_format_params + "\" % "+log_params+")")
  95. printMocReturn(module_name, func, indent+1)
  96. print("")
  97. def generate_function_doc(module_name, func, prefix):
  98. if documentation is not None and module_name in documentation:
  99. function_parts = func['name'].split("_")
  100. for i in range(len(function_parts), 0, -1):
  101. function_prefix = "_".join(function_parts[:i])
  102. if function_prefix in documentation[module_name]["functions"]:
  103. print(prefix + "\t\"\"\"")
  104. documentation_lines = documentation[module_name]["functions"][function_prefix].split("\n")
  105. for line in documentation_lines:
  106. print(prefix + "\t" + line.replace("\\", "\\\\\\\\"))
  107. print(prefix + "\t\"\"\"")
  108. break
  109. classes = defaultdict(list)
  110. if len(sys.argv) < 2:
  111. print("Please specify the json file to parse")
  112. sys.exit(-1)
  113. documentation = None
  114. if len(sys.argv) > 2:
  115. for i in range(2,len(sys.argv)):
  116. if sys.argv[i] == "--no-union":
  117. noUnion = True
  118. else:
  119. with open(sys.argv[i]) as f:
  120. documentation = json.load(f)
  121. if not noUnion:
  122. print("from typing import Union")
  123. print("import sys")
  124. print("import types")
  125. print("_mock_data = {}")
  126. print("")
  127. with open(sys.argv[1]) as f:
  128. data = json.load(f)
  129. for method in data['result']['methods']:
  130. classes[method['func']['module']].append(method['func'])
  131. if "pv" not in classes:
  132. classes['pv'].append({'params': 'str',
  133. 'ret': 'xval',
  134. 'name': 'get'}
  135. )
  136. classes['pv'].append({'params': 'str',
  137. 'ret': 'xval',
  138. 'name': 'gete'}
  139. )
  140. classes['pv'].append({'params': 'str, int',
  141. 'ret': 'xval',
  142. 'name': 'getvn'}
  143. )
  144. classes['pv'].append({'params': 'str, str',
  145. 'ret': 'xval',
  146. 'name': 'getvs'}
  147. )
  148. classes['pv'].append({'params': 'str',
  149. 'ret': 'xval',
  150. 'name': 'getw'}
  151. )
  152. classes['pv'].append({'params': 'str, int',
  153. 'ret': 'none',
  154. 'name': 'seti'}
  155. )
  156. classes['pv'].append({'params': 'str, str',
  157. 'ret': 'none',
  158. 'name': 'sets'}
  159. )
  160. classes['pv'].append({'params': 'str',
  161. 'ret': 'none',
  162. 'name': 'unset'}
  163. )
  164. classes['pv'].append({'params': 'str',
  165. 'ret': 'none',
  166. 'name': 'is_null'}
  167. )
  168. for module_name, module in classes.items():
  169. if module_name != "":
  170. print("")
  171. print("class " + module_name.capitalize() + ":")
  172. for func in module:
  173. printFunction(module_name, func, 1)
  174. for func in classes['']:
  175. print("")
  176. printFunction('', func, 0)
  177. def document_module(module_name):
  178. if documentation is not None and module_name in documentation:
  179. print("\"\"\"")
  180. documentation_lines = documentation[module_name]["overview"].split("\n")
  181. for line in documentation_lines:
  182. print("" + line)
  183. print("\"\"\"")
  184. for module_name in classes.keys():
  185. if module_name != "":
  186. if module_name in reserved_keywords:
  187. print("setattr(sys.modules[__name__], '" + module_name + "', " + module_name.capitalize() + "())")
  188. else:
  189. print(module_name + " = "+module_name.capitalize()+"()")
  190. document_module(module_name)
  191. print("")
  192. for module_name in classes.keys():
  193. print("_mock_data['" + module_name + "'] = {}")