shell.pyx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # cython: profile=False
  4. import os
  5. import sys
  6. import subprocess
  7. from Naked.settings import debug as DEBUG_FLAG
  8. #------------------------------------------------------------------------------
  9. # [ execute function ] (boolean)
  10. # run a shell command and print std out / std err to terminal
  11. # returns True if exit status = 0
  12. # returns False if exit status != 0
  13. #------------------------------------------------------------------------------
  14. def execute(command):
  15. try:
  16. response = subprocess.call(command, shell=True)
  17. if response == 0:
  18. return True
  19. else:
  20. return False
  21. except subprocess.CalledProcessError as cpe:
  22. try:
  23. sys.stderr.write(cpe.output)
  24. except TypeError as te:
  25. sys.stderr.write(str(cpe.output))
  26. except Exception as e:
  27. if DEBUG_FLAG:
  28. sys.stderr.write("Naked Framework Error: unable to run the shell command with the execute() function (Naked.toolshed.shell.py).")
  29. raise e
  30. #------------------------------------------------------------------------------
  31. # [ run function ] (bytes string or False)
  32. # run a shell command
  33. # default =
  34. # success:: print to std out and return the std out string
  35. # error:: print to stderr return False, suppress SystemExit on error to permit ongoing run of calling script
  36. # suppress_stdout = True >> suppress std output stream print (returns string)
  37. # suppress_stderr = True >> suppress std err stream print (returns False)
  38. # suppress_exit_status_call = False >> raise SystemExit with the returned status code
  39. #------------------------------------------------------------------------------
  40. def run(command, suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
  41. try:
  42. response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
  43. if not suppress_stdout:
  44. print(response)
  45. return response
  46. except subprocess.CalledProcessError as cpe:
  47. if not suppress_stderr: # error in existing application (non-zero exit status)
  48. try:
  49. sys.stderr.write(cpe.output)
  50. except TypeError as te: # deal with unusual errors from some system executables that return non string type through subprocess.check_output
  51. sys.stderr.write(str(cpe.output))
  52. if not suppress_exit_status_call:
  53. if cpe.returncode:
  54. sys.exit(cpe.returncode)
  55. else:
  56. sys.exit(1)
  57. return False # return False on non-zero exit status codes (i.e. failures in the subprocess executable)
  58. except Exception as e:
  59. if DEBUG_FLAG:
  60. sys.stderr.write("Naked Framework Error: unable to run the shell command with the run() function (Naked.toolshed.shell.py).")
  61. raise e
  62. #------------------------------------------------------------------------------
  63. # [ muterun function ] (NakedObject with attributes for stdout, stderr, exitcode)
  64. # run a shell command and return a response object
  65. # return object attributes : stdout (bytes), stderr (bytes), exitcode (int)
  66. #------------------------------------------------------------------------------
  67. def muterun(command):
  68. try:
  69. from Naked.toolshed.types import NakedObject
  70. response_obj = NakedObject()
  71. response = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
  72. response_obj.stdout = response
  73. response_obj.exitcode = 0
  74. response_obj.stderr = b""
  75. return response_obj
  76. except subprocess.CalledProcessError as cpe:
  77. response_obj.stdout = b""
  78. response_obj.stderr = cpe.output
  79. if cpe.returncode:
  80. response_obj.exitcode = cpe.returncode
  81. else:
  82. response_obj.exitcode = 1
  83. return response_obj
  84. except Exception as e:
  85. if DEBUG_FLAG:
  86. sys.stderr.write("Naked Framework Error: unable to run the shell command with the mute_run() function (Naked.toolshed.shell.py).")
  87. raise e
  88. #------------------------------------------------------------------------------
  89. # RUBY COMMAND EXECUTION
  90. #------------------------------------------------------------------------------
  91. #------------------------------------------------------------------------------
  92. # [ execute_rb function ] (boolean)
  93. # execute a ruby script file in a shell subprocess
  94. #------------------------------------------------------------------------------
  95. def execute_rb(file_path, arguments=""):
  96. try:
  97. if len(arguments) > 0:
  98. rb_command = 'ruby ' + file_path + " " + arguments
  99. else:
  100. rb_command = 'ruby ' + file_path
  101. return execute(rb_command) # return result of execute() of the ruby file
  102. except Exception as e:
  103. if DEBUG_FLAG:
  104. sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
  105. raise e
  106. #------------------------------------------------------------------------------
  107. # [ run_rb function ] (bytes string or False)
  108. # execute a ruby script file in a shell subprocess, return the output
  109. #------------------------------------------------------------------------------
  110. def run_rb(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
  111. try:
  112. if len(arguments) > 0:
  113. rb_command = 'ruby ' + file_path + " " + arguments
  114. else:
  115. rb_command = 'ruby ' + file_path
  116. return run(rb_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of the ruby file
  117. except Exception as e:
  118. if DEBUG_FLAG:
  119. sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_rb() function (Naked.toolshed.shell.py).")
  120. raise e
  121. #------------------------------------------------------------------------------
  122. # [ muterun_rb function ] (NakedObject response object)
  123. #------------------------------------------------------------------------------
  124. def muterun_rb(file_path, arguments=""):
  125. try:
  126. if len(arguments) > 0:
  127. rb_command = 'ruby ' + file_path + " " + arguments
  128. else:
  129. rb_command = 'ruby ' + file_path
  130. return muterun(rb_command) # return result of muterun() of the ruby file
  131. except Exception as e:
  132. if DEBUG_FLAG:
  133. sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_rb() function (Naked.toolshed.shell.py).")
  134. raise e
  135. #------------------------------------------------------------------------------
  136. # NODE.JS COMMAND EXECUTION
  137. #------------------------------------------------------------------------------
  138. #------------------------------------------------------------------------------
  139. # [ execute_js function ] (boolean)
  140. # execute a node.js script file in a shell subprocess
  141. # stdout stream to terminal
  142. # returns True for success (=0) exit status code
  143. # returns False for unsuccessful (!=0) exit status code
  144. #------------------------------------------------------------------------------
  145. def execute_js(file_path, arguments=""):
  146. try:
  147. if len(arguments) > 0:
  148. js_command = 'node ' + file_path + " " + arguments
  149. else:
  150. js_command = 'node ' + file_path
  151. return execute(js_command) # return result of execute() of node.js file
  152. except Exception as e:
  153. if DEBUG_FLAG:
  154. sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
  155. raise e
  156. #------------------------------------------------------------------------------
  157. # [ run_js function ] (byte string or False)
  158. # execute a node.js script file in a shell subprocess
  159. # print the standard output to the standard output stream by default
  160. # set suppress_output to True to suppress stream to standard output. String is still returned to calling function
  161. # set suppress_exit_status_call to True to suppress raising sys.exit on failures with shell subprocess exit status code (if available) or 1 if not available
  162. # returns the standard output byte string from the subprocess executable on success
  163. # returns False if the subprocess exits with a non-zero exit code
  164. #------------------------------------------------------------------------------
  165. def run_js(file_path, arguments="", suppress_stdout=False, suppress_stderr=False, suppress_exit_status_call=True):
  166. try:
  167. if len(arguments) > 0:
  168. js_command = 'node ' + file_path + " " + arguments
  169. else:
  170. js_command = 'node ' + file_path
  171. return run(js_command, suppress_stdout, suppress_stderr, suppress_exit_status_call) # return result of run() of node.js file
  172. except Exception as e:
  173. if DEBUG_FLAG:
  174. sys.stderr.write("Naked Framework Error: unable to run the shell command with the run_js() function (Naked.toolshed.shell.py).")
  175. raise e
  176. #------------------------------------------------------------------------------
  177. # [ muterun_js function ] (NakedObject response object)
  178. #------------------------------------------------------------------------------
  179. def muterun_js(file_path, arguments=""):
  180. try:
  181. if len(arguments) > 0:
  182. js_command = 'node ' + file_path + " " + arguments
  183. else:
  184. js_command = 'node ' + file_path
  185. return muterun(js_command) # return result of muterun() of node.js file
  186. except Exception as e:
  187. if DEBUG_FLAG:
  188. sys.stderr.write("Naked Framework Error: unable to run the shell command with the muterun_js() function (Naked.toolshed.shell.py).")
  189. raise e
  190. #------------------------------------------------------------------------------
  191. # [ Environment Class ]
  192. # shell environment variables class
  193. # self.env = the environment variable dictionary
  194. # self.vars = the environment variable names list
  195. #------------------------------------------------------------------------------
  196. class Environment():
  197. def __init__(self):
  198. self.env = os.environ
  199. self.vars = list(os.environ.keys())
  200. #------------------------------------------------------------------------------
  201. # [ is_var method ] (boolean)
  202. # return boolean for presence of a variable name in the shell environment
  203. #------------------------------------------------------------------------------
  204. def is_var(self, var_name):
  205. try:
  206. return (var_name in self.vars)
  207. except Exception as e:
  208. if DEBUG_FLAG:
  209. sys.stderr.write("Naked Framework Error: unable to determine if the variable is included in the shell variable list with the is_var() method (Naked.toolshed.shell).")
  210. raise e
  211. #------------------------------------------------------------------------------
  212. # [ get_var method ] (string)
  213. # get the variable value for a variable in the shell environment list
  214. # returns empty string if the variable is not included in the environment variable list
  215. #------------------------------------------------------------------------------
  216. def get_var(self, var_name):
  217. try:
  218. if var_name in self.vars:
  219. return self.env[var_name]
  220. else:
  221. return ""
  222. except Exception as e:
  223. if DEBUG_FLAG:
  224. sys.stderr.write("Naked Framework Error: unable to return the requested shell variable with the get_var() method (Naked.toolshed.shell).")
  225. raise e
  226. #------------------------------------------------------------------------------
  227. # [ get_split_var_list method ] (list of strings)
  228. # return a list of strings split by OS dependent separator from the shell variable assigment string
  229. # if the variable name is not in the environment list, returns an empty list
  230. #------------------------------------------------------------------------------
  231. def get_split_var_list(self, var_name):
  232. try:
  233. if var_name in self.vars:
  234. return self.env[var_name].split(os.pathsep)
  235. else:
  236. return []
  237. except Exception as e:
  238. if DEBUG_FLAG:
  239. sys.stderr.write("Naked Framework Error: unable to return environment variable list with the get_split_var_list() method (Naked.toolshed.shell).")
  240. raise e
  241. if __name__ == '__main__':
  242. pass
  243. # e = Environment()
  244. # pathlist = e.get_split_var_list("PATH")
  245. # for item in pathlist:
  246. # print(item)