PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/framework/pym/play/commands/base.py

https://bitbucket.org/verpage/play
Python | 333 lines | 325 code | 7 blank | 1 comment | 14 complexity | ef808f45cb35a123f110b5ce5806d6c1 MD5 | raw file
  1. # Command related to creation and execution: run, new, clean, test, auto-test
  2. import sys
  3. import os
  4. import subprocess
  5. import shutil
  6. import getopt
  7. import urllib2
  8. import webbrowser
  9. import time
  10. import signal
  11. from play.utils import *
  12. COMMANDS = ['run', 'new', 'clean', 'test', 'autotest', 'auto-test', 'id', 'new,run', 'clean,run', 'modules']
  13. HELP = {
  14. 'id': "Define the framework ID",
  15. 'new': "Create a new application",
  16. 'clean': "Delete temporary files (including the bytecode cache)",
  17. 'run': "Run the application in the current shell",
  18. 'test': "Run the application in test mode in the current shell",
  19. 'auto-test': "Automatically run all application tests",
  20. 'modules': "Display the computed modules list"
  21. }
  22. def execute(**kargs):
  23. command = kargs.get("command")
  24. app = kargs.get("app")
  25. args = kargs.get("args")
  26. env = kargs.get("env")
  27. cmdloader = kargs.get("cmdloader")
  28. if command == 'id':
  29. id(env)
  30. if command == 'new' or command == 'new,run':
  31. new(app, args, env, cmdloader)
  32. if command == 'clean' or command == 'clean,run':
  33. clean(app)
  34. if command == 'new,run' or command == 'clean,run' or command == 'run':
  35. run(app, args)
  36. if command == 'test':
  37. test(app, args)
  38. if command == 'auto-test' or command == 'autotest':
  39. autotest(app, args)
  40. if command == 'modules':
  41. show_modules(app, args)
  42. def new(app, args, env, cmdloader=None):
  43. withModules = []
  44. application_name = None
  45. try:
  46. optlist, args = getopt.getopt(args, '', ['with=', 'name='])
  47. for o, a in optlist:
  48. if o in ('--with'):
  49. withModules = a.split(',')
  50. if o in ('--name'):
  51. application_name = a
  52. except getopt.GetoptError, err:
  53. print "~ %s" % str(err)
  54. print "~ Sorry, unrecognized option"
  55. print "~ "
  56. sys.exit(-1)
  57. if os.path.exists(app.path):
  58. print "~ Oops. %s already exists" % app.path
  59. print "~"
  60. sys.exit(-1)
  61. md = []
  62. for m in withModules:
  63. dirname = None
  64. if os.path.exists(os.path.join(env["basedir"], 'modules/%s' % m)) and os.path.isdir(os.path.join(env["basedir"], 'modules/%s' % m)):
  65. dirname = m
  66. else:
  67. for f in os.listdir(os.path.join(env["basedir"], 'modules')):
  68. if os.path.isdir(os.path.join(env["basedir"], 'modules/%s' % f)) and f.find('%s-' % m) == 0:
  69. dirname = f
  70. break
  71. if not dirname:
  72. print "~ Oops. No module %s found" % m
  73. print "~ Try to install it using 'play install %s'" % m
  74. print "~"
  75. sys.exit(-1)
  76. md.append(dirname)
  77. print "~ The new application will be created in %s" % os.path.normpath(app.path)
  78. if application_name is None:
  79. application_name = raw_input("~ What is the application name? [%s] " % os.path.basename(app.path))
  80. if application_name == "":
  81. application_name = os.path.basename(app.path)
  82. copy_directory(os.path.join(env["basedir"], 'resources/application-skel'), app.path)
  83. os.mkdir(os.path.join(app.path, 'app/models'))
  84. os.mkdir(os.path.join(app.path, 'lib'))
  85. app.check()
  86. replaceAll(os.path.join(app.path, 'conf/application.conf'), r'%APPLICATION_NAME%', application_name)
  87. replaceAll(os.path.join(app.path, 'conf/application.conf'), r'%SECRET_KEY%', secretKey())
  88. print "~"
  89. # Configure modules
  90. runDepsAfter = False
  91. for m in md:
  92. # Check dependencies.yml of the module
  93. depsYaml = os.path.join(env["basedir"], 'modules/%s/conf/dependencies.yml' % m)
  94. if os.path.exists(depsYaml):
  95. deps = open(depsYaml).read()
  96. try:
  97. moduleDefinition = re.search(r'self:\s*(.*)\s*', deps).group(1)
  98. replaceAll(os.path.join(app.path, 'conf/dependencies.yml'), r'- play\n', '- play\n - %s\n' % moduleDefinition )
  99. runDepsAfter = True
  100. except Exception:
  101. pass
  102. if runDepsAfter:
  103. cmdloader.commands['dependencies'].execute(command='dependencies', app=app, args=['--sync'], env=env, cmdloader=cmdloader)
  104. print "~ OK, the application is created."
  105. print "~ Start it with : play run %s" % sys.argv[2]
  106. print "~ Have fun!"
  107. print "~"
  108. process = None
  109. def handle_sigterm(signum, frame):
  110. global process
  111. if 'process' in globals():
  112. process.terminate()
  113. sys.exit(0)
  114. first_sigint = True
  115. def handle_sigint(signum, frame):
  116. global process
  117. global first_sigint
  118. if 'process' in globals():
  119. if first_sigint:
  120. # Prefix with new line because ^C usually appears on the terminal
  121. print "\nTerminating Java process"
  122. process.terminate()
  123. first_sigint = False
  124. else:
  125. print "\nKilling Java process"
  126. process.kill()
  127. def run(app, args):
  128. global process
  129. app.check()
  130. print "~ Ctrl+C to stop"
  131. print "~ "
  132. java_cmd = app.java_cmd(args)
  133. try:
  134. process = subprocess.Popen (java_cmd, env=os.environ)
  135. signal.signal(signal.SIGTERM, handle_sigterm)
  136. return_code = process.wait()
  137. signal.signal(signal.SIGINT, handle_sigint)
  138. if 0 != return_code:
  139. sys.exit(return_code)
  140. except OSError:
  141. print "Could not execute the java executable, please make sure the JAVA_HOME environment variable is set properly (the java executable should reside at JAVA_HOME/bin/java). "
  142. sys.exit(-1)
  143. print
  144. def clean(app):
  145. app.check()
  146. print "~ Deleting %s" % os.path.normpath(os.path.join(app.path, 'tmp'))
  147. if os.path.exists(os.path.join(app.path, 'tmp')):
  148. shutil.rmtree(os.path.join(app.path, 'tmp'))
  149. print "~"
  150. def show_modules(app, args):
  151. app.check()
  152. modules = app.modules()
  153. if len(modules):
  154. print "~ Application modules are:"
  155. print "~ "
  156. for module in modules:
  157. print "~ %s" % module
  158. else:
  159. print "~ No modules installed in this application"
  160. print "~ "
  161. sys.exit(0)
  162. def test(app, args):
  163. app.check()
  164. java_cmd = app.java_cmd(args)
  165. print "~ Running in test mode"
  166. print "~ Ctrl+C to stop"
  167. print "~ "
  168. try:
  169. return_code = subprocess.call(java_cmd, env=os.environ)
  170. if 0 != return_code:
  171. sys.exit(return_code)
  172. except OSError:
  173. print "Could not execute the java executable, please make sure the JAVA_HOME environment variable is set properly (the java executable should reside at JAVA_HOME/bin/java). "
  174. sys.exit(-1)
  175. print
  176. def autotest(app, args):
  177. app.check()
  178. print "~ Running in test mode"
  179. print "~ Ctrl+C to stop"
  180. print "~ "
  181. print "~ Deleting %s" % os.path.normpath(os.path.join(app.path, 'tmp'))
  182. if os.path.exists(os.path.join(app.path, 'tmp')):
  183. shutil.rmtree(os.path.join(app.path, 'tmp'))
  184. print "~"
  185. # Kill if exists
  186. http_port = 9000
  187. protocol = 'http'
  188. if app.readConf('https.port'):
  189. http_port = app.readConf('https.port')
  190. protocol = 'https'
  191. else:
  192. http_port = app.readConf('http.port')
  193. try:
  194. proxy_handler = urllib2.ProxyHandler({})
  195. opener = urllib2.build_opener(proxy_handler)
  196. opener.open('http://localhost:%s/@kill' % http_port)
  197. except Exception, e:
  198. pass
  199. # Do not run the app if SSL is configured and no cert store is configured
  200. keystore = app.readConf('keystore.file')
  201. if protocol == 'https' and not keystore:
  202. print "https without keystore configured. play auto-test will fail. Exiting now."
  203. sys.exit(-1)
  204. # Run app
  205. test_result = os.path.join(app.path, 'test-result')
  206. if os.path.exists(test_result):
  207. shutil.rmtree(test_result)
  208. sout = open(os.path.join(app.log_path(), 'system.out'), 'w')
  209. java_cmd = app.java_cmd(args)
  210. try:
  211. play_process = subprocess.Popen(java_cmd, env=os.environ, stdout=sout)
  212. except OSError:
  213. print "Could not execute the java executable, please make sure the JAVA_HOME environment variable is set properly (the java executable should reside at JAVA_HOME/bin/java). "
  214. sys.exit(-1)
  215. soutint = open(os.path.join(app.log_path(), 'system.out'), 'r')
  216. while True:
  217. if play_process.poll():
  218. print "~"
  219. print "~ Oops, application has not started?"
  220. print "~"
  221. sys.exit(-1)
  222. line = soutint.readline().strip()
  223. if line:
  224. print line
  225. if line.find('Server is up and running') > -1: # This line is written out by Server.java to system.out and is not log file dependent
  226. soutint.close()
  227. break
  228. # Run FirePhoque
  229. print "~"
  230. headless_browser = ''
  231. if app.readConf('headlessBrowser'):
  232. headless_browser = app.readConf('headlessBrowser')
  233. fpcp = [os.path.join(app.play_env["basedir"], 'modules/testrunner/lib/play-testrunner.jar')]
  234. fpcp_libs = os.path.join(app.play_env["basedir"], 'modules/testrunner/firephoque')
  235. for jar in os.listdir(fpcp_libs):
  236. if jar.endswith('.jar'):
  237. fpcp.append(os.path.normpath(os.path.join(fpcp_libs, jar)))
  238. cp_args = ':'.join(fpcp)
  239. if os.name == 'nt':
  240. cp_args = ';'.join(fpcp)
  241. java_cmd = [app.java_path(), '-classpath', cp_args, '-Dapplication.url=%s://localhost:%s' % (protocol, http_port), '-DheadlessBrowser=%s' % (headless_browser), 'play.modules.testrunner.FirePhoque']
  242. if protocol == 'https':
  243. java_cmd.insert(-1, '-Djavax.net.ssl.trustStore=' + app.readConf('keystore.file'))
  244. try:
  245. subprocess.call(java_cmd, env=os.environ)
  246. except OSError:
  247. print "Could not execute the headless browser. "
  248. sys.exit(-1)
  249. print "~"
  250. time.sleep(1)
  251. # Kill if exists
  252. try:
  253. proxy_handler = urllib2.ProxyHandler({})
  254. opener = urllib2.build_opener(proxy_handler)
  255. opener.open('%s://localhost:%s/@kill' % (protocol, http_port))
  256. except Exception, e:
  257. pass
  258. if os.path.exists(os.path.join(app.path, 'test-result/result.passed')):
  259. print "~ All tests passed"
  260. print "~"
  261. testspassed = True
  262. if os.path.exists(os.path.join(app.path, 'test-result/result.failed')):
  263. print "~ Some tests have failed. See file://%s for results" % test_result
  264. print "~"
  265. sys.exit(1)
  266. def id(play_env):
  267. if not play_env["id"]:
  268. print "~ framework ID is not set"
  269. new_id = raw_input("~ What is the new framework ID (or blank to unset)? ")
  270. if new_id:
  271. print "~"
  272. print "~ OK, the framework ID is now %s" % new_id
  273. print "~"
  274. open(play_env["id_file"], 'w').write(new_id)
  275. else:
  276. print "~"
  277. print "~ OK, the framework ID is unset"
  278. print "~"
  279. if os.path.exists(play_env["id_file"]):
  280. os.remove(play_env["id_file"])
  281. # ~~~~~~~~~ UTILS
  282. def kill(pid):
  283. if os.name == 'nt':
  284. import ctypes
  285. handle = ctypes.windll.kernel32.OpenProcess(1, False, int(pid))
  286. if not ctypes.windll.kernel32.TerminateProcess(handle, 0):
  287. print "~ Cannot kill the process with pid %s (ERROR %s)" % (pid, ctypes.windll.kernel32.GetLastError())
  288. print "~ "
  289. sys.exit(-1)
  290. else:
  291. try:
  292. os.kill(int(pid), 15)
  293. except OSError:
  294. print "~ Play was not running (Process id %s not found)" % pid
  295. print "~"
  296. sys.exit(-1)