def main():
	try:
		if 'frozen' in dir(sys) and sys.platform.startswith("darwin"):
			user_library_dir = path.expanduser('~/Library/Trigger Toolkit')
			app_version_path = workspace.path('trigger/version.txt')
			installed_version_path = path.join(user_library_dir, 'trigger/version.txt')

			if not path.exists(user_library_dir):
				LOG.debug('First time run, copying toolkit code into %s' % user_library_dir)
				_install_to_library(user_library_dir)

			if not path.exists(installed_version_path):
				LOG.debug('No version file, copying toolkit code into %s' % user_library_dir)
				_install_to_library(user_library_dir)

			else:
				installed_version = _version_tuple(_read_file(installed_version_path))
				app_version = _version_tuple(_read_file(app_version_path))

				if app_version > installed_version:
					LOG.debug('App version newer than installed version, copying toolkit code into %s' % user_library_dir)
					_install_to_library(user_library_dir)

				elif app_version == installed_version:
					LOG.debug("Installed version is same as App version, using code from %s" % user_library_dir)

				else:
					LOG.debug("Installed version is newer than App version, using code from %s" % user_library_dir)

			LOG.debug('Changing workspace to %s' % user_library_dir)
			workspace.WORKSPACE = user_library_dir

		# Import system openssl on linux before adding our library paths.
		if sys.platform.startswith("linux"):
			try:
				import OpenSSL
			except ImportError:
				raise Exception("PyOpenSSL is required to use Trigger Toolkit.")

		root = workspace.path()
		sys.path.insert(0, root)
		sys.path.insert(0, os.path.join(root, 'trigger-dependencies'))
		sys.path.insert(0, os.path.join(root, 'build-tools'))
		sys.path.insert(0, os.path.join(root, 'build-tools', 'forge-dependencies'))

		multiprocessing.freeze_support()
		# import using a string here so pyinstaller doesn't try to include
		# trigger code inside the final binary
		trigger = __import__('trigger.web')
		launch_browser = '--no-launch' not in sys.argv
		trigger.web.main(launch_browser)
	except Exception as e:
		import traceback
		# TODO: show user something useful when not running in a console setting
		print "Unhandled exception in Trigger Toolkit: %s" % e
		traceback.print_exc()
		print "Please contact [email protected]"
		raw_input("Press enter to continue")
def serve_templates():
	bottle.response.content_type = 'text/javascript'

	templates = {}

	for dirpath, dirnames, filenames in os.walk(workspace.path('static/templates')):
		for filename in filenames:
			rel_path = path.join(dirpath, filename)[len(workspace.path('static/templates'))+1:]
			if rel_path.endswith('.html'):
				template_name = rel_path[:-5].replace('\\', '/')

				with open(path.join(dirpath, filename)) as template_file:
					templates[template_name] = template_file.read()

	return "var ToolkitTemplates = " + json.dumps(templates)
def main(launch_browser=True, port=None):
	"""Be wary when changing the signature for this method, it is expected by the TriggerToolkit binary to accept
	at least the following positional args:

	:param launch_browser: If true, try to open the preferred web browser after starting the toolkit server.
	:param port: If this is not None, use the given port for the toolkit server (only really used for testing purposes).
	"""
	lib.setup_log_to_file('startup.log', backup=True)
	try:
		# Check for port file
		if '--testing' not in sys.argv:
			port_file_path = workspace.path('.trigger_port')
			if path.exists(port_file_path):
				with open(port_file_path, 'r') as port_file:
					previous_port = int(port_file.read())

				try:
					r = requests.get('https://%s:%d/' % ('toolkit-local.com', previous_port), timeout=0.5)
					if r.status_code == 200:
						LOG.info('Existing toolkit detected at port: %d' % previous_port)
						url = 'https://%s:%d/' % ('toolkit-local.com', previous_port)
						if launch_browser:
							lib.open_url(url)
						return
				except:
					pass

		updater.update_and_restart_if_necessary()

		# delay import to prevent locking binary dependencies
		from trigger import webserver
		webserver.run_server(launch_browser)
	except Exception:
		LOG.error("Uncaught exception in main", exc_info=True)
		sys.exit(1)
def toolkit_updater():
	"""Construct an Updater which can update the toolkit distribution."""
	import workspace
	return Updater(
		zip_url='latest_toolkit',
		extract_to=workspace.path()
	)
def _run_server(launch_browser, port):
	global server, session_manager

	port_file = open(port_file_path, 'w')
	port_file.write(str(port))
	port_file.close()
	url = 'https://%s:%d/' % ('toolkit-local.com', port)

	LOG.debug('Toolkit startup complete, closing startup.log')
	lib.close_log_to_file('startup.log')
	lib.setup_toolkit_log(backup=True)

	from cherrypy import wsgiserver
	server_address = ('127.0.0.1', port)
	LOG.info('Starting up webserver at {0:s}'.format(server_address))
	server = wsgiserver.CherryPyWSGIServer(server_address, app, numthreads=30, shutdown_timeout=0.01)
	server.ssl_certificate = workspace.path('https/toolkit-local_com.crt')
	server.ssl_certificate_chain = workspace.path('https/toolkit-local_com-chain.crt')
	server.ssl_private_key = workspace.path('https/toolkit-local_com.key')

	def sd():
		LOG.debug('Starting shutdown of Toolkit web server: %s' % time.time())
		thread.interrupt_main()
	session_manager = SessionManagerProxy(shutdown=sd, shutdown_when_no_sessions=('--testing' not in sys.argv))

	timer = None
	if launch_browser:
		timer = threading.Timer(2, lib.open_url, args=(url,))
		timer.start()

	try:
		server.start()
	finally:
		LOG.debug('Web server process quitting %s' % time.time())
		try:
			if timer:
				timer.cancel()
		except Exception as e:
			LOG.error("Error in finally", exc_info=True)
			pass
def setup_log_to_file(filename, backup):
	"""Setup logging to a file in the directory the Toolkit is installed into."""
	path_to_log_to = workspace.path(filename)
	try:
		if backup:
			incremental_backup_file(path_to_log_to)

		file_handler = logging.FileHandler(path_to_log_to)

		# adb seems to get a lock on the log file if we don't have this
		disable_file_inheritance(file_handler.stream)

		file_handler.setLevel(logging.DEBUG)
		file_handler.setFormatter(RpcAwareFormatter(logging.Formatter('%(asctime)s PID:%(process)d [%(name)s:%(levelname)7s] %(message)s')))
		logging.root.addHandler(file_handler)
		file_handlers[filename] = file_handler
	except OSError:
		LOG.error("Couldn't create %s for log output, carrying on anyway." % filename)
def run_server(launch_browser):
	if '--testing' in sys.argv:
		port = 5000
	else:
		port = 38394

		with open(workspace.path('build-tools', 'forge_build.json'), 'r') as forge_build_file:
			try:
				forge_build_dict = json.load(forge_build_file)
				port = forge_build_dict['port']
			except Exception:
				pass

	if sys.platform.startswith("darwin") and ('--testing' not in sys.argv):
		# important to fork here, motivation is that we want
		# to be able to run TriggerToolkit.app repeatedly on OSX
		lib.fork_and_run(lambda: _run_server(launch_browser, port))

	else:
		_run_server(launch_browser, port)
def _install_to_library(user_library_dir):
	_copy_ontop_of(workspace.path(), user_library_dir)
def embed():
	bottle.request.environ['HTTP_IF_MODIFIED_SINCE'] = None
	bottle.response.content_type = 'text/html'

	with codecs.open(os.path.join(workspace.path('static'), 'index.html'), 'r') as index_file:
		return pystache.render(index_file.read(), {'embed': True, 'debug': build_config.load().get('debug', False)})
def serve_static(filename):
	"""Serve up any other static file."""
	if filename.endswith(".png"):
		return static_file_uncached(filename, root=workspace.path('static'), mimetype='image/png')
	return static_file_uncached(filename, root=workspace.path('static'))
def index():
	bottle.request.environ['HTTP_IF_MODIFIED_SINCE'] = None
	bottle.response.content_type = 'text/html'

	with codecs.open(os.path.join(workspace.path('static'), 'index.html'), 'r') as index_file:
		return pystache.render(index_file.read(), {'embed': False, 'debug': build_config.load().get('debug', False)})

@app.route('/embed')
def embed():
	bottle.request.environ['HTTP_IF_MODIFIED_SINCE'] = None
	bottle.response.content_type = 'text/html'

	with codecs.open(os.path.join(workspace.path('static'), 'index.html'), 'r') as index_file:
		return pystache.render(index_file.read(), {'embed': True, 'debug': build_config.load().get('debug', False)})

port_file_path = workspace.path('.trigger_port')

def _run_server(launch_browser, port):
	global server, session_manager

	port_file = open(port_file_path, 'w')
	port_file.write(str(port))
	port_file.close()
	url = 'https://%s:%d/' % ('toolkit-local.com', port)

	LOG.debug('Toolkit startup complete, closing startup.log')
	lib.close_log_to_file('startup.log')
	lib.setup_toolkit_log(backup=True)

	from cherrypy import wsgiserver
	server_address = ('127.0.0.1', port)
Exemple #12
0
def normalized_path_relative_to_toolkit(path):
	return os.path.join(workspace.path(), os.path.normpath(path))