transmit `node_state` from js to python done
parent
587a02b30a
commit
a52a90c45e
@ -1,9 +1,16 @@
|
||||
from flask import Flask, render_template
|
||||
import json
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
def hello():
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/download', methods=['POST'])
|
||||
def downloadModel():
|
||||
modelNodeStates = request.get_json()
|
||||
print(modelNodeStates)
|
||||
return 'OK', 200
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@ -1,34 +0,0 @@
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .server import start
|
||||
from .server import stop
|
||||
from .server import status
|
||||
from .server import wait
|
||||
from .server import serve
|
||||
from .__version__ import __version__
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Viewer for neural network, deep learning and machine learning models.')
|
||||
parser.add_argument('file', metavar='MODEL_FILE', help='model file to serve', nargs='?', default=None)
|
||||
parser.add_argument('-v', '--version', help="print version", action='store_true')
|
||||
parser.add_argument('-b', '--browse', help='launch web browser', action='store_true')
|
||||
parser.add_argument('-p', '--port', help='port to serve', type=int)
|
||||
parser.add_argument('--host', help="host to serve")
|
||||
parser.add_argument('--log', help='log details to console', action='store_true')
|
||||
args = parser.parse_args()
|
||||
if args.file and not os.path.exists(args.file):
|
||||
print("Model file '" + args.file + "' does not exist.")
|
||||
sys.exit(2)
|
||||
if args.version:
|
||||
print(__version__)
|
||||
sys.exit(0)
|
||||
address = (args.host, args.port) if args.host else args.port if args.port else None
|
||||
start(args.file, address=address, browse=args.browse, log=args.log)
|
||||
wait()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1 +0,0 @@
|
||||
__version__ = '0.0.0'
|
||||
@ -1,298 +0,0 @@
|
||||
|
||||
import codecs
|
||||
import errno
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import webbrowser
|
||||
import time
|
||||
|
||||
from .__version__ import __version__
|
||||
|
||||
if sys.version_info[0] > 2:
|
||||
from urllib.parse import urlparse
|
||||
from urllib.parse import unquote
|
||||
from http.server import HTTPServer
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from socketserver import ThreadingMixIn
|
||||
else:
|
||||
from urlparse import urlparse
|
||||
from urlparse import unquote
|
||||
from BaseHTTPServer import HTTPServer
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
from SocketServer import ThreadingMixIn
|
||||
|
||||
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
def handler(self):
|
||||
if not hasattr(self, 'mime_types_map'):
|
||||
self.mime_types_map = {
|
||||
'.html': 'text/html',
|
||||
'.js': 'text/javascript',
|
||||
'.css': 'text/css',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.ico': 'image/x-icon',
|
||||
'.json': 'application/json',
|
||||
'.pb': 'application/octet-stream',
|
||||
'.ttf': 'font/truetype',
|
||||
'.otf': 'font/opentype',
|
||||
'.eot': 'application/vnd.ms-fontobject',
|
||||
'.woff': 'font/woff',
|
||||
'.woff2': 'application/font-woff2',
|
||||
'.svg': 'image/svg+xml'
|
||||
}
|
||||
pathname = urlparse(self.path).path
|
||||
folder = os.path.dirname(os.path.realpath(__file__))
|
||||
location = folder + pathname
|
||||
status_code = 0
|
||||
headers = {}
|
||||
buffer = None
|
||||
data = '/data/'
|
||||
if status_code == 0:
|
||||
if pathname == '/':
|
||||
meta = []
|
||||
meta.append('<meta name="type" content="Python">')
|
||||
meta.append('<meta name="version" content="' + __version__ + '">')
|
||||
if self.file:
|
||||
meta.append('<meta name="file" content="/data/' + self.file + '">')
|
||||
with codecs.open(location + 'index.html', mode="r", encoding="utf-8") as open_file:
|
||||
buffer = open_file.read()
|
||||
buffer = re.sub(r'<meta name="version" content="\d+.\d+.\d+">', '\n'.join(meta), buffer)
|
||||
buffer = buffer.encode('utf-8')
|
||||
headers['Content-Type'] = 'text/html'
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
elif pathname.startswith(data):
|
||||
file = pathname[len(data):]
|
||||
if file == self.file and self.data:
|
||||
buffer = self.data
|
||||
else:
|
||||
file = self.folder + '/' + unquote(file)
|
||||
status_code = 404
|
||||
if os.path.exists(file):
|
||||
with open(file, 'rb') as binary:
|
||||
buffer = binary.read()
|
||||
if buffer:
|
||||
headers['Content-Type'] = 'application/octet-stream'
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
else:
|
||||
if os.path.exists(location) and not os.path.isdir(location):
|
||||
extension = os.path.splitext(location)[1]
|
||||
content_type = self.mime_types_map[extension]
|
||||
if content_type:
|
||||
with open(location, 'rb') as binary:
|
||||
buffer = binary.read()
|
||||
headers['Content-Type'] = content_type
|
||||
headers['Content-Length'] = len(buffer)
|
||||
status_code = 200
|
||||
else:
|
||||
status_code = 404
|
||||
if self.log:
|
||||
sys.stdout.write(str(status_code) + ' ' + self.command + ' ' + self.path + '\n')
|
||||
sys.stdout.flush()
|
||||
self.send_response(status_code)
|
||||
for key in headers:
|
||||
self.send_header(key, headers[key])
|
||||
self.end_headers()
|
||||
if self.command != 'HEAD':
|
||||
if status_code == 404 and buffer is None:
|
||||
self.wfile.write(bytes(status_code))
|
||||
elif (status_code in (200, 404)) and buffer is not None:
|
||||
self.wfile.write(buffer)
|
||||
def do_GET(self):
|
||||
self.handler()
|
||||
def do_HEAD(self):
|
||||
self.handler()
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
pass
|
||||
|
||||
class HTTPServerThread(threading.Thread):
|
||||
def __init__(self, data, file, address, log):
|
||||
threading.Thread.__init__(self)
|
||||
self.address = address
|
||||
self.url = 'http://' + address[0] + ':' + str(address[1])
|
||||
self.file = file
|
||||
self.server = ThreadedHTTPServer(address, HTTPRequestHandler)
|
||||
self.server.timeout = 0.25
|
||||
if file:
|
||||
self.server.RequestHandlerClass.folder = os.path.dirname(file) if os.path.dirname(file) else '.'
|
||||
self.server.RequestHandlerClass.file = os.path.basename(file)
|
||||
else:
|
||||
self.server.RequestHandlerClass.folder = ''
|
||||
self.server.RequestHandlerClass.file = ''
|
||||
self.server.RequestHandlerClass.data = data
|
||||
self.server.RequestHandlerClass.log = log
|
||||
self.terminate_event = threading.Event()
|
||||
self.terminate_event.set()
|
||||
self.stop_event = threading.Event()
|
||||
|
||||
def run(self):
|
||||
self.stop_event.clear()
|
||||
self.terminate_event.clear()
|
||||
try:
|
||||
while not self.stop_event.is_set():
|
||||
self.server.handle_request()
|
||||
except Exception:
|
||||
pass
|
||||
self.terminate_event.set()
|
||||
self.stop_event.clear()
|
||||
|
||||
def stop(self):
|
||||
if self.alive():
|
||||
sys.stdout.write("Stopping " + self.url + "\n")
|
||||
self.stop_event.set()
|
||||
self.server.server_close()
|
||||
self.terminate_event.wait(1000)
|
||||
|
||||
def alive(self):
|
||||
return not self.terminate_event.is_set()
|
||||
|
||||
_thread_list = []
|
||||
|
||||
def _add_thread(thread):
|
||||
global _thread_list
|
||||
_thread_list.append(thread)
|
||||
|
||||
def _update_thread_list(address=None):
|
||||
global _thread_list
|
||||
_thread_list = [ thread for thread in _thread_list if thread.alive() ]
|
||||
threads = _thread_list
|
||||
if address is not None:
|
||||
address = _make_address(address)
|
||||
if address[1] is None:
|
||||
threads = [ thread for thread in threads if address[0] == thread.address[0] ]
|
||||
else:
|
||||
threads = [ thread for thread in threads if address[0] == thread.address[0] and address[1] == thread.address[1] ]
|
||||
return threads
|
||||
|
||||
def _make_address(address):
|
||||
if address is None or isinstance(address, int):
|
||||
port = address
|
||||
address = ('localhost', port)
|
||||
if isinstance(address, tuple) and len(address) == 2:
|
||||
host = address[0]
|
||||
port = address[1]
|
||||
if isinstance(host, str) and (port is None or isinstance(port, int)):
|
||||
return address
|
||||
raise ValueError('Invalid address.')
|
||||
|
||||
def _make_port(address):
|
||||
if address[1] is None or address[1] == 0:
|
||||
ports = []
|
||||
if address[1] != 0:
|
||||
ports.append(8080)
|
||||
ports.append(8081)
|
||||
rnd = random.Random()
|
||||
for _ in range(4):
|
||||
port = rnd.randrange(15000, 25000)
|
||||
if port not in ports:
|
||||
ports.append(port)
|
||||
ports.append(0)
|
||||
for port in ports:
|
||||
temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
temp_socket.settimeout(1)
|
||||
try:
|
||||
temp_socket.bind((address[0], port))
|
||||
sockname = temp_socket.getsockname()
|
||||
address = (address[0], sockname[1])
|
||||
return address
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
temp_socket.close()
|
||||
if isinstance(address[1], int):
|
||||
return address
|
||||
raise ValueError('Failed to allocate port.')
|
||||
|
||||
def stop(address=None):
|
||||
'''Stop serving model at address.
|
||||
|
||||
Args:
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
'''
|
||||
threads = _update_thread_list(address)
|
||||
for thread in threads:
|
||||
thread.stop()
|
||||
_update_thread_list()
|
||||
|
||||
def status(adrress=None):
|
||||
'''Is model served at address.
|
||||
|
||||
Args:
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
'''
|
||||
threads = _update_thread_list(adrress)
|
||||
return len(threads) > 0
|
||||
|
||||
def wait():
|
||||
'''Wait for console exit and stop all model servers.'''
|
||||
try:
|
||||
while len(_update_thread_list()) > 0:
|
||||
time.sleep(1000)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.flush()
|
||||
stop()
|
||||
|
||||
def serve(file, data, address=None, browse=False, log=False):
|
||||
'''Start serving model from file or data buffer at address and open in web browser.
|
||||
|
||||
Args:
|
||||
file (string): Model file to serve. Required to detect format.
|
||||
data (bytes): Model data to serve. None will load data from file.
|
||||
log (bool, optional): Log details to console. Default: False
|
||||
browse (bool, optional): Launch web browser. Default: True
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
|
||||
Returns:
|
||||
A (host, port) address tuple.
|
||||
'''
|
||||
if not data and file and not os.path.exists(file):
|
||||
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file)
|
||||
|
||||
_update_thread_list()
|
||||
address = _make_address(address)
|
||||
if isinstance(address[1], int) and address[1] != 0:
|
||||
stop(address)
|
||||
else:
|
||||
address = _make_port(address)
|
||||
_update_thread_list()
|
||||
|
||||
thread = HTTPServerThread(data, file, address, log)
|
||||
thread.start()
|
||||
while not thread.alive():
|
||||
time.sleep(10)
|
||||
_add_thread(thread)
|
||||
|
||||
if file:
|
||||
sys.stdout.write("Serving '" + file + "' at " + thread.url + "\n")
|
||||
else:
|
||||
sys.stdout.write("Serving at " + thread.url + "\n")
|
||||
sys.stdout.flush()
|
||||
if browse:
|
||||
webbrowser.open(thread.url)
|
||||
|
||||
return address
|
||||
|
||||
def start(file=None, address=None, browse=True, log=False):
|
||||
'''Start serving model file at address and open in web browser.
|
||||
|
||||
Args:
|
||||
file (string): Model file to serve.
|
||||
log (bool, optional): Log details to console. Default: False
|
||||
browse (bool, optional): Launch web browser, Default: True
|
||||
address (tuple, optional): A (host, port) tuple, or a port number.
|
||||
|
||||
Returns:
|
||||
A (host, port) address tuple.
|
||||
'''
|
||||
return serve(file, None, browse=browse, address=address, log=log)
|
||||
@ -1,256 +0,0 @@
|
||||
|
||||
// Experimental
|
||||
|
||||
var weka = weka || {};
|
||||
var json = json || require('./json');
|
||||
var java = {};
|
||||
|
||||
weka.ModelFactory = class {
|
||||
|
||||
match(context) {
|
||||
try {
|
||||
const stream = context.stream;
|
||||
if (stream.length >= 5) {
|
||||
const signature = [ 0xac, 0xed ];
|
||||
if (stream.peek(2).every((value, index) => value === signature[index])) {
|
||||
const reader = new java.io.InputObjectStream(stream);
|
||||
const obj = reader.read();
|
||||
if (obj && obj.$class && obj.$class.name) {
|
||||
return 'weka';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
// continue regardless of error
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
open(context) {
|
||||
return Promise.resolve().then(() => {
|
||||
const reader = new java.io.InputObjectStream(context.stream);
|
||||
const obj = reader.read();
|
||||
throw new weka.Error("Unsupported type '" + obj.$class.name + "'.");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
weka.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Weka model.';
|
||||
}
|
||||
};
|
||||
|
||||
java.io = {};
|
||||
|
||||
java.io.InputObjectStream = class {
|
||||
|
||||
constructor(stream) {
|
||||
// Object Serialization Stream Protocol
|
||||
// https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/serialization/spec/protocol.doc.html
|
||||
if (stream.length < 5) {
|
||||
throw new java.io.Error('Invalid stream size');
|
||||
}
|
||||
const signature = [ 0xac, 0xed ];
|
||||
if (!stream.peek(2).every((value, index) => value === signature[index])) {
|
||||
throw new java.io.Error('Invalid stream signature');
|
||||
}
|
||||
this._reader = new java.io.InputObjectStream.BinaryReader(stream.peek());
|
||||
this._references = [];
|
||||
this._reader.skip(2);
|
||||
const version = this._reader.uint16();
|
||||
if (version !== 0x0005) {
|
||||
throw new java.io.Error("Unsupported version '" + version + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
read() {
|
||||
return this._object();
|
||||
}
|
||||
|
||||
_object() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x73: { // TC_OBJECT
|
||||
const obj = {};
|
||||
obj.$class = this._classDesc();
|
||||
this._newHandle(obj);
|
||||
this._classData(obj);
|
||||
return obj;
|
||||
}
|
||||
case 0x74: { // TC_STRING
|
||||
return this._newString(false);
|
||||
}
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_classDesc() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x72: // TC_CLASSDESC
|
||||
this._reader.skip(-1);
|
||||
return this._newClassDesc();
|
||||
case 0x71: // TC_REFERENCE
|
||||
return this._references[this._reader.uint32() - 0x7e0000];
|
||||
case 0x70: // TC_NULL
|
||||
this._reader.byte();
|
||||
return null;
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_newClassDesc() {
|
||||
const code = this._reader.byte();
|
||||
switch (code) {
|
||||
case 0x72: { // TC_CLASSDESC
|
||||
const classDesc = {};
|
||||
classDesc.name = this._reader.string(),
|
||||
classDesc.id = this._reader.uint64().toString();
|
||||
this._newHandle(classDesc);
|
||||
classDesc.flags = this._reader.byte();
|
||||
classDesc.fields = [];
|
||||
const count = this._reader.uint16();
|
||||
for (let i = 0; i < count; i++) {
|
||||
const field = {};
|
||||
field.type = String.fromCharCode(this._reader.byte());
|
||||
field.name = this._reader.string();
|
||||
if (field.type === '[' || field.type === 'L') {
|
||||
field.classname = this._object();
|
||||
}
|
||||
classDesc.fields.push(field);
|
||||
}
|
||||
if (this._reader.byte() !== 0x78) {
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
classDesc.superClass = this._classDesc();
|
||||
return classDesc;
|
||||
}
|
||||
case 0x7D: // TC_PROXYCLASSDESC
|
||||
break;
|
||||
}
|
||||
throw new java.io.Error("Unsupported code '" + code + "'.");
|
||||
}
|
||||
|
||||
_classData(/* obj */) {
|
||||
/*
|
||||
const classname = obj.$class.name;
|
||||
let flags = obj.$class.flags;
|
||||
let superClass = obj.$class.superClass;
|
||||
while (superClass) {
|
||||
flags |= superClass.flags;
|
||||
superClass = superClass.superClass;
|
||||
}
|
||||
if (flags & 0x02) { // SC_SERIALIZABLE
|
||||
debugger;
|
||||
var customObject = objects[classname];
|
||||
var hasReadObjectMethod = customObject && customObject.readObject;
|
||||
if (flags & 0x01) { // SC_WRITE_METHOD
|
||||
if (!hasReadObjectMethod) {
|
||||
throw new Error('Class "'+ classname + '" dose not implement readObject()');
|
||||
}
|
||||
customObject.readObject(this, obj);
|
||||
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hasReadObjectMethod) {
|
||||
customObject.readObject(this, obj);
|
||||
if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
|
||||
throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._nowrclass(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & 0x04) { // SC_EXTERNALIZABLE
|
||||
if (flags & 0x08) { // SC_BLOCK_DATA
|
||||
this._objectAnnotation(obj);
|
||||
}
|
||||
else {
|
||||
this._externalContents();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('Illegal flags: ' + flags);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
_newString(long) {
|
||||
const value = this._reader.string(long);
|
||||
this._newHandle(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
_newHandle(obj) {
|
||||
this._references.push(obj);
|
||||
}
|
||||
};
|
||||
|
||||
java.io.InputObjectStream.BinaryReader = class {
|
||||
|
||||
constructor(buffer) {
|
||||
this._buffer = buffer;
|
||||
this._position = 0;
|
||||
this._length = buffer.length;
|
||||
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
||||
this._decoder = new TextDecoder('utf-8');
|
||||
}
|
||||
|
||||
skip(offset) {
|
||||
this._position += offset;
|
||||
if (this._position > this._end) {
|
||||
throw new java.io.Error('Expected ' + (this._position - this._end) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
byte() {
|
||||
const position = this._position;
|
||||
this.skip(1);
|
||||
return this._buffer[position];
|
||||
}
|
||||
|
||||
uint16() {
|
||||
const position = this._position;
|
||||
this.skip(2);
|
||||
return this._view.getUint16(position, false);
|
||||
}
|
||||
|
||||
uint32() {
|
||||
const position = this._position;
|
||||
this.skip(4);
|
||||
return this._view.getUint32(position, false);
|
||||
}
|
||||
|
||||
uint64() {
|
||||
const position = this._position;
|
||||
this.skip(8);
|
||||
return this._view.getUint64(position, false);
|
||||
}
|
||||
|
||||
string(long) {
|
||||
const size = long ? this.uint64().toNumber() : this.uint16();
|
||||
const position = this._position;
|
||||
this.skip(size);
|
||||
return this._decoder.decode(this._buffer.subarray(position, this._position));
|
||||
}
|
||||
};
|
||||
|
||||
java.io.Error = class extends Error {
|
||||
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'Error loading Object Serialization Stream Protocol.';
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||
module.exports.ModelFactory = weka.ModelFactory;
|
||||
}
|
||||
Loading…
Reference in New Issue