[pypy-commit] jitviewer default: make the jitviewer more like a standalone application: it automatically starts a lightweight browser, and stops the server when the user closes it
antocuni
noreply at buildbot.pypy.org
Wed Jun 8 18:38:23 CEST 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r122:380ae1af309b
Date: 2011-06-08 18:22 +0200
http://bitbucket.org/pypy/jitviewer/changeset/380ae1af309b/
Log: make the jitviewer more like a standalone application: it
automatically starts a lightweight browser, and stops the server
when the user closes it
diff --git a/bin/jitviewer.py b/bin/jitviewer.py
--- a/bin/jitviewer.py
+++ b/bin/jitviewer.py
@@ -1,9 +1,16 @@
#!/usr/bin/env pypy-c
""" A web-based browser of your log files. Run by
- jitviewer.py <path to your log file> [port]
+ jitviewer.py <path to your log file> [port] [--server]
-and point your browser to http://localhost:5000
+By default, this script will also start a lightweight PyQT/QWebKit based
+browser pointing at the jitviewer. This assumes that CPython is installed in
+/usr/bin/python, and that PyQT with WebKit support is installed.
+
+If you want to run only the server, you can pass the --server option. In this
+case, you can access the jitviewer by visiting http://localhost:5000 with your
+favorite browser.
+
Demo logfile available in this directory as 'log'.
To produce the logfile for your program, run:
@@ -33,6 +40,8 @@
import cgi
import flask
import inspect
+import threading
+import time
from pypy.tool.logparser import parse_log_file, extract_category
from pypy.tool.jitlogparser.storage import LoopStorage
from pypy.tool.jitlogparser.parser import adjust_bridges
@@ -129,24 +138,28 @@
'callstack': callstack}
return flask.jsonify(d)
-def start_browser(url):
- import time
- import webbrowser
- import threading
- def run():
- time.sleep(0.5) # give the server some time to start
- webbrowser.open(url)
- th = threading.Thread(target=run)
- th.start()
- return th
class OverrideFlask(flask.Flask):
root_path = property(lambda self: self._root_path, lambda *args: None)
def __init__(self, *args, **kwargs):
self._root_path = kwargs.pop('root_path')
+ self.servers = []
+ self.evil_monkeypatch()
flask.Flask.__init__(self, *args, **kwargs)
+ def evil_monkeypatch(self):
+ """
+ Evil way to fish the server started by flask, necessary to be able to shut
+ it down cleanly."""
+ from SocketServer import BaseServer
+ orig___init__ = BaseServer.__init__
+ def __init__(self2, *args, **kwds):
+ self.servers.append(self2)
+ orig___init__(self2, *args, **kwds)
+ BaseServer.__init__ = __init__
+
+
class CheckingLoopStorage(LoopStorage):
def disassemble_code(self, fname, startlineno, name):
result = super(CheckingLoopStorage, self).disassemble_code(fname, startlineno, name)
@@ -154,6 +167,7 @@
raise CannotFindFile(fname)
return result
+
def main():
PATH = os.path.join(os.path.dirname(
os.path.dirname(_jitviewer.__file__)))
@@ -161,11 +175,18 @@
if not '__pypy__' in sys.builtin_module_names:
print "Please run it using pypy-c"
sys.exit(1)
+ #
+ server_mode = False
+ if '--server' in sys.argv:
+ server_mode = True
+ sys.argv.remove('--server')
+ #
if len(sys.argv) != 2 and len(sys.argv) != 3:
print __doc__
sys.exit(1)
- log = parse_log_file(sys.argv[1])
- extra_path = os.path.dirname(sys.argv[1])
+ filename = sys.argv[1]
+ log = parse_log_file(filename)
+ extra_path = os.path.dirname(filename)
if len(sys.argv) != 3:
port = 5000
else:
@@ -180,9 +201,38 @@
app.debug = True
app.route('/')(server.index)
app.route('/loop')(server.loop)
- #th = start_browser('http://localhost:5000/')
- app.run(use_reloader=False, host='0.0.0.0', port=port)
- #th.join()
+ def run():
+ app.run(use_reloader=False, host='0.0.0.0', port=port)
+
+ if server_mode:
+ run()
+ else:
+ url = "http://localhost:%d/" % port
+ run_server_and_browser(app, run, url, filename)
+
+def run_server_and_browser(app, run, url, filename):
+ # start the HTTP server in another thread
+ th = threading.Thread(target=run)
+ th.start()
+ #
+ # start the webkit browser in the main thread (actually, it's a subprocess, but still)
+ time.sleep(0.5) # give the server some time to start
+ ret = start_browser(url, filename)
+ #
+ # shutdown the HTPP server and wait until it completes
+ app.servers[0].shutdown()
+ th.join()
+
+def start_browser(url, filename):
+ import subprocess
+ qwebview_py = os.path.join(os.path.dirname(__file__), 'qwebview.py')
+ title = "jitviewer: " + filename
+ try:
+ return subprocess.check_call(['/usr/bin/python', qwebview_py, url, title])
+ except Exception, e:
+ print 'Cannot start the builtin browser: %s' % e
+ print "Please point your browser to: %s" % url
+ raw_input("Press enter to quit and kill the server")
if __name__ == '__main__':
main()
diff --git a/bin/qwebview.py b/bin/qwebview.py
new file mode 100644
--- /dev/null
+++ b/bin/qwebview.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+import sys
+from PyQt4.QtCore import QUrl
+from PyQt4.QtGui import QApplication
+from PyQt4.QtWebKit import QWebView
+
+def main():
+ if len(sys.argv) == 2:
+ url = sys.argv[1]
+ title = url
+ elif len(sys.argv) == 3:
+ url = sys.argv[1]
+ title = sys.argv[2]
+ else:
+ print >> sys.stderr, "Usage: qwebview.py URL [title]"
+ return 1
+
+ app = QApplication(sys.argv)
+ web = QWebView()
+ web.setMinimumSize(1024, 800)
+ web.setWindowTitle(title)
+ web.load(QUrl(url))
+ web.show()
+ return app.exec_()
+
+if __name__ == '__main__':
+ sys.exit(main())
More information about the pypy-commit
mailing list