import webbrowser, threading, os, time, subprocess, tempfile, sys, shutil
qecp = None
def register(module):
global qecp
qecp = module
def serve(host='localhost', port=52665, data_folder=".", return_server=False, quiet=True):
from bottle import WSGIRefServer, route, abort, run, response, static_file
global visualizer_website
def guess_mime(filename):
if filename.endswith("html"):
response.content_type = 'text/html; charset=utf8'
elif filename.endswith("js"):
response.content_type = 'text/javascript; charset=utf8'
elif filename.endswith("json"):
response.content_type = 'application/json; charset=utf8'
@route('/data/<filename:path>')
def send_data(filename):
return static_file(filename, root=data_folder)
@route('/')
@route('/<filename:path>')
def send_root(filename=""):
if filename == "":
filename = "index.html"
if filename in visualizer_website:
guess_mime(filename)
return visualizer_website[filename]
abort(404)
server = WSGIRefServer(host=host, port=port)
def run_server():
run(server=server, quiet=quiet)
if return_server:
return server, run_server
run_server()
def open_visualizer(filename, host='localhost', port=52666, data_folder=".", open_browser=True, quiet=True):
server, run_server = serve(host, port, data_folder, return_server=True, quiet=quiet)
threading.Thread(target=run_server).start()
if open_browser:
def open_browser():
webbrowser.open(f"http://{host}:{port}/?filename={filename}")
threading.Timer(0.5, open_browser).start() print("Hit ENTER to exit server.")
input()
server.srv.shutdown()
time.sleep(0.3)
def run_command_get_stdout(command, no_stdout=True, use_tmp_out=False, stderr_to_stdout=False, cwd=None):
env = os.environ.copy()
stdout = subprocess.PIPE
if use_tmp_out:
out_file = tempfile.NamedTemporaryFile(delete=False)
out_filename = out_file.name
stdout = out_file
if no_stdout:
stdout = sys.stdout
process = subprocess.Popen(command, universal_newlines=True, env=env, stdout=stdout
, stderr=(stdout if stderr_to_stdout else sys.stderr), cwd=cwd)
stdout, _ = process.communicate()
if use_tmp_out:
out_file.flush()
out_file.close()
with open(out_filename, "r", encoding="utf8") as f:
stdout = f.read()
os.remove(out_filename)
return stdout, process.returncode
def local_render_visualizer(
filename, image_filename="rendered", renderer_folder="./local_renderer", width=1024, height=1024
, data_folder=".", snapshot_idx=0, patch_script=None):
if not os.path.exists(renderer_folder):
os.makedirs(renderer_folder)
global visualizer_website
for website_filename in visualizer_website:
filepath = os.path.join(renderer_folder, website_filename)
with open(filepath, "w", encoding="utf-8") as f:
f.write(visualizer_website[website_filename])
if not os.path.exists(os.path.join(renderer_folder, "node_modules")):
run_command_get_stdout(["npm", "install"], cwd=renderer_folder)
if patch_script is not None:
patch_filename = f"{filename}.patch.js"
with open(os.path.join(renderer_folder, patch_filename), "w", encoding="utf8") as f:
f.write(patch_script)
renderer_data_folder = os.path.join(renderer_folder, "data")
if not os.path.exists(renderer_data_folder):
os.makedirs(renderer_data_folder)
shutil.copy2(os.path.join(data_folder, filename), renderer_data_folder)
domain = "http://localhost" url = f"{domain}?filename={filename}&snapshot_idx={snapshot_idx}"
if patch_script is not None:
url += f"&patch_url=./{patch_filename}"
commands = ["node", "index.js", url, f"{width}", f"{height}", image_filename]
print(f"[run] {commands}")
run_command_get_stdout(commands, cwd=renderer_folder)