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)
def normalized_path_relative_to_toolkit(path): return os.path.join(workspace.path(), os.path.normpath(path))