blob: 6165432e7af8458a91cf93c55a024ea68b0ee287 [file] [log] [blame]
#!/usr/bin/env python
from __future__ import print_function
"""The clang static analyzer results viewer.
"""
import sys
import imp
import os
import posixpath
import threading
import time
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
import webbrowser
# How long to wait for server to start.
kSleepTimeout = .05
kMaxSleeps = int(60 / kSleepTimeout)
# Default server parameters
kDefaultHost = '127.0.0.1'
kDefaultPort = 8181
kMaxPortsToTry = 100
###
def url_is_up(url):
try:
o = urlopen(url)
except IOError:
return False
o.close()
return True
def start_browser(port, options):
import webbrowser
url = 'http://%s:%d' % (options.host, port)
# Wait for server to start...
if options.debug:
sys.stderr.write('%s: Waiting for server.' % sys.argv[0])
sys.stderr.flush()
for i in range(kMaxSleeps):
if url_is_up(url):
break
if options.debug:
sys.stderr.write('.')
sys.stderr.flush()
time.sleep(kSleepTimeout)
else:
print('WARNING: Unable to detect that server started.', file=sys.stderr)
if options.debug:
print('%s: Starting webbrowser...' % sys.argv[0], file=sys.stderr)
webbrowser.open(url)
def run(port, options, root):
# Prefer to look relative to the installed binary
share = os.path.dirname(__file__) + "/../share/scan-view"
if not os.path.isdir(share):
# Otherwise look relative to the source
share = os.path.dirname(__file__) + "/../../scan-view/share"
sys.path.append(share)
import ScanView
try:
print('Starting scan-view at: http://%s:%d' % (options.host,
port))
print(' Use Ctrl-C to exit.')
httpd = ScanView.create_server((options.host, port),
options, root)
httpd.serve_forever()
except KeyboardInterrupt:
pass
def port_is_open(port):
try:
import socketserver
except ImportError:
import SocketServer as socketserver
try:
t = socketserver.TCPServer((kDefaultHost, port), None)
except:
return False
t.server_close()
return True
def main():
import argparse
parser = argparse.ArgumentParser(description="The clang static analyzer "
"results viewer.")
parser.add_argument("root", metavar="<results directory>", type=str)
parser.add_argument(
'--host', dest="host", default=kDefaultHost, type=str,
help="Host interface to listen on. (default=%s)" % kDefaultHost)
parser.add_argument('--port', dest="port", default=None, type=int,
help="Port to listen on. (default=%s)" % kDefaultPort)
parser.add_argument("--debug", dest="debug", default=0,
action="count",
help="Print additional debugging information.")
parser.add_argument("--auto-reload", dest="autoReload", default=False,
action="store_true",
help="Automatically update module for each request.")
parser.add_argument("--no-browser", dest="startBrowser", default=True,
action="store_false",
help="Don't open a webbrowser on startup.")
parser.add_argument("--allow-all-hosts", dest="onlyServeLocal",
default=True, action="store_false",
help='Allow connections from any host (access '
'restricted to "127.0.0.1" by default)')
args = parser.parse_args()
# Make sure this directory is in a reasonable state to view.
if not posixpath.exists(posixpath.join(args.root, 'index.html')):
parser.error('Invalid directory, analysis results not found!')
# Find an open port. We aren't particularly worried about race
# conditions here. Note that if the user specified a port we only
# use that one.
if args.port is not None:
port = args.port
else:
for i in range(kMaxPortsToTry):
if port_is_open(kDefaultPort + i):
port = kDefaultPort + i
break
else:
parser.error('Unable to find usable port in [%d,%d)' %
(kDefaultPort, kDefaultPort+kMaxPortsToTry))
# Kick off thread to wait for server and start web browser, if
# requested.
if args.startBrowser:
threading.Thread(target=start_browser, args=(port, args)).start()
run(port, args, args.root)
if __name__ == '__main__':
main()