Skip to content

Commit 273301f

Browse files
committed
Cleaning up the App._instance.
1 parent 9c974ef commit 273301f

4 files changed

Lines changed: 74 additions & 68 deletions

File tree

editor/editor.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -783,16 +783,5 @@ def on_dropped(self, left, top):
783783
self.style['top']=top
784784

785785

786-
def main():
787-
#p = Project()
788-
#root = p.load('./example_project.py')
789-
#p.append(root, "root")
790-
#p.save(None)
791-
792-
# starts the webserver
793-
# optional parameters
794-
# start(MyApp,address='127.0.0.1', port=8081, multiple_instance=False,enable_file_cache=True, update_interval=0.1, start_browser=True)
795-
start(Editor, debug=False, address='0.0.0.0', port=8082, update_interval=0.01)
796-
797786
if __name__ == "__main__":
798-
main()
787+
start(Editor, debug=False, address='0.0.0.0', port=8082, update_interval=0.01, multiple_instance=True)

editor/editor_widgets.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,17 @@ def show(self, *args):
306306

307307
def add_fileinput_field(self, defaultname='untitled'):
308308
self.txtFilename = gui.TextInput()
309-
self.txtFilename.onchange.connect(self.on_enter_key_pressed)
309+
self.txtFilename.onkeydown.connect(self.on_enter_key_pressed)
310310
self.txtFilename.set_text(defaultname)
311311

312312
self.add_field_with_label("filename","Filename",self.txtFilename)
313313

314314
def get_fileinput_value(self):
315315
return self.get_field('filename').get_value()
316316

317-
def on_enter_key_pressed(self, widget, value):
318-
self.confirm_value(None)
317+
def on_enter_key_pressed(self, widget, value, keycode):
318+
if keycode=="13":
319+
self.confirm_value(None)
319320

320321
@gui.decorate_event
321322
def confirm_value(self, widget):

remi/gui.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -952,17 +952,18 @@ def __init__(self, *args, **kwargs):
952952
self._classes = []
953953

954954
def repr(self, changed_widgets=None):
955-
"""It is used to automatically represent the object to HTML format
956-
packs all the attributes, children and so on.
955+
"""It is used to automatically represent the object to HTML format
956+
packs all the attributes, children and so on.
957957
958-
Args:
959-
changed_widgets (dict): A dictionary containing a collection of tags that have to be updated.
960-
The tag that have to be updated is the key, and the value is its textual repr.
961-
"""
962-
if changed_widgets is None:
963-
changed_widgets={}
964-
local_changed_widgets = {}
965-
return ''.join(('<', self.type, '>\n', self.innerHTML(local_changed_widgets), '\n</', self.type, '>'))
958+
Args:
959+
changed_widgets (dict): A dictionary containing a collection of tags that have to be updated.
960+
The tag that have to be updated is the key, and the value is its textual repr.
961+
"""
962+
if changed_widgets is None:
963+
changed_widgets={}
964+
local_changed_widgets = {}
965+
self._set_updated()
966+
return ''.join(('<', self.type, '>\n', self.innerHTML(local_changed_widgets), '\n</', self.type, '>'))
966967

967968

968969
class HEAD(Tag):
@@ -1240,6 +1241,7 @@ def repr(self, changed_widgets=None):
12401241
if changed_widgets is None:
12411242
changed_widgets={}
12421243
local_changed_widgets = {}
1244+
self._set_updated()
12431245
return ''.join(('<', self.type, '>\n', self.innerHTML(local_changed_widgets), '\n</', self.type, '>'))
12441246

12451247

@@ -1663,7 +1665,9 @@ def __init__(self, single_line=True, hint='', *args, **kwargs):
16631665
elem.value = elem.value.split('\\n').join('');
16641666
var params={};params['new_value']=elem.value;
16651667
sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);
1666-
}""" % {'emitter_identifier': str(self.identifier), 'event_name': Widget.EVENT_ONCHANGE}
1668+
}
1669+
event.stopPropagation();event.preventDefault();return false;
1670+
""" % {'emitter_identifier': str(self.identifier), 'event_name': Widget.EVENT_ONCHANGE}
16671671
#else:
16681672
# self.attributes[self.EVENT_ONINPUT] = """
16691673
# var elem = document.getElementById('%(emitter_identifier)s');
@@ -1718,7 +1722,8 @@ def onchange(self, new_value):
17181722
@decorate_set_on_listener("(self, emitter, new_value, keycode)")
17191723
@decorate_event_js("""var elem=document.getElementById('%(emitter_identifier)s');
17201724
var params={};params['new_value']=elem.value;params['keycode']=(event.which||event.keyCode);
1721-
sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
1725+
sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);
1726+
event.stopPropagation();event.preventDefault();return false;""")
17221727
def onkeyup(self, new_value, keycode):
17231728
"""Called when user types and releases a key into the TextInput
17241729
@@ -1733,7 +1738,8 @@ def onkeyup(self, new_value, keycode):
17331738
@decorate_set_on_listener("(self, emitter, new_value, keycode)")
17341739
@decorate_event_js("""var elem=document.getElementById('%(emitter_identifier)s');
17351740
var params={};params['new_value']=elem.value;params['keycode']=(event.which||event.keyCode);
1736-
sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);""")
1741+
sendCallbackParam('%(emitter_identifier)s','%(event_name)s',params);
1742+
event.stopPropagation();event.preventDefault();return false;""")
17371743
def onkeydown(self, new_value, keycode):
17381744
"""Called when the user types a key into the TextInput.
17391745

remi/server.py

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,7 @@ class App(BaseHTTPRequestHandler, object):
296296
re_attr_call = re.compile(r"^/*(\w+)\/(\w+)\?{0,1}(\w*\={1}(\w|\.)+\&{0,1})*$")
297297

298298
def __init__(self, request, client_address, server, **app_args):
299-
self.update_lock = threading.RLock()
300299
self._app_args = app_args
301-
self.client = None
302300
self.root = None
303301
self._log = logging.getLogger('remi.request')
304302
super(App, self).__init__(request, client_address, server)
@@ -340,50 +338,62 @@ def _instance(self):
340338
#send session to browser
341339
del self.headers['cookie']
342340

341+
#if the client instance doesn't exist
343342
if not(self.session in clients):
344-
runtimeInstances[str(id(self))] = self
345-
clients[self.session] = self
346-
347-
net_interface_ip = self.headers.get('Host', "%s:%s"%(self.connection.getsockname()[0],self.server.server_address[1]))
343+
net_interface_ip = self.headers.get('Host', "%s:%s"%(self.connection.getsockname()[0],self.server.server_address[1]))
348344

349-
websocket_timeout_timer_ms = str(self.server.websocket_timeout_timer_ms)
350-
pending_messages_queue_length = str(self.server.pending_messages_queue_length)
351-
clients[self.session].update_interval = self.server.update_interval
345+
websocket_timeout_timer_ms = str(self.server.websocket_timeout_timer_ms)
346+
pending_messages_queue_length = str(self.server.pending_messages_queue_length)
347+
self.update_interval = self.server.update_interval
352348

353-
354-
self.client = clients[self.session]
355-
356-
if not hasattr(self.client, 'page'):
357349
from remi import gui
358350

359351
head = gui.HEAD(self.server.title,
360352
net_interface_ip, pending_messages_queue_length, websocket_timeout_timer_ms)
361-
with open(self.client._get_static_file('style.css'), 'rb') as f:
353+
with open(self._get_static_file('style.css'), 'rb') as f:
362354
md5 = hashlib.md5(f.read()).hexdigest()
363355
# use the default css, but append a version based on its hash, to stop browser caching
364356
head.add_child('internal_css', "<link href='/res/style.css?%s' rel='stylesheet' />\n" % md5)
365357

366358
body = gui.BODY()
367-
body.onload.connect(self.client.onload)
368-
body.onerror.connect(self.client.onerror)
369-
body.ononline.connect(self.client.ononline)
370-
body.onpagehide.connect(self.client.onpagehide)
371-
body.onpageshow.connect(self.client.onpageshow)
372-
body.onresize.connect(self.client.onresize)
373-
self.client.page = gui.HTML()
374-
self.client.page.add_child('head', head)
375-
self.client.page.add_child('body', body)
376-
377-
if not hasattr(clients[self.session], 'websockets'):
378-
clients[self.session].websockets = []
379-
380-
if not hasattr(clients[self.session], '_need_update_flag'):
381-
clients[self.session]._need_update_flag = False
382-
clients[self.session]._stop_update_flag = False
383-
if clients[self.session].update_interval > 0:
384-
clients[self.session]._update_thread = threading.Thread(target=self._idle_loop)
385-
clients[self.session]._update_thread.setDaemon(True)
386-
clients[self.session]._update_thread.start()
359+
body.onload.connect(self.onload)
360+
body.onerror.connect(self.onerror)
361+
body.ononline.connect(self.ononline)
362+
body.onpagehide.connect(self.onpagehide)
363+
body.onpageshow.connect(self.onpageshow)
364+
body.onresize.connect(self.onresize)
365+
self.page = gui.HTML()
366+
self.page.add_child('head', head)
367+
self.page.add_child('body', body)
368+
369+
if not hasattr(self, 'websockets'):
370+
self.websockets = []
371+
372+
self.update_lock = threading.RLock()
373+
374+
if not hasattr(self, '_need_update_flag'):
375+
self._need_update_flag = False
376+
self._stop_update_flag = False
377+
if self.update_interval > 0:
378+
self._update_thread = threading.Thread(target=self._idle_loop)
379+
self._update_thread.setDaemon(True)
380+
self._update_thread.start()
381+
382+
runtimeInstances[str(id(self))] = self
383+
clients[self.session] = self
384+
else:
385+
#restore instance attributes
386+
client = clients[self.session]
387+
388+
self.websockets = client.websockets
389+
self.page = client.page
390+
391+
self.update_lock = client.update_lock
392+
393+
self.update_interval = client.update_interval
394+
self._need_update_flag = client._need_update_flag
395+
if hasattr(client, '_update_thread'):
396+
self._update_thread = client._update_thread
387397

388398
def main(self, *_):
389399
""" Subclasses of App class *must* declare a main function
@@ -451,15 +461,15 @@ def set_root_widget(self, widget):
451461
self._send_spontaneous_websocket_message(msg)
452462

453463
def _send_spontaneous_websocket_message(self, message):
454-
for ws in self.client.websockets:
464+
for ws in self.websockets:
455465
# noinspection PyBroadException
456466
try:
457467
#self._log.debug("sending websocket spontaneous message")
458468
ws.send_message(message)
459469
except:
460470
self._log.error("sending websocket spontaneous message", exc_info=True)
461471
try:
462-
self.client.websockets.remove(ws)
472+
self.websockets.remove(ws)
463473
ws.close()
464474
except:
465475
self._log.error("unable to remove websocket client - already not in list", exc_info=True)
@@ -571,9 +581,9 @@ def do_GET(self):
571581
# build the page (call main()) in user code, if not built yet
572582
with self.update_lock:
573583
# build the root page once if necessary
574-
if not 'root' in self.client.page.children['body'].children.keys():
584+
if not 'root' in self.page.children['body'].children.keys():
575585
self._log.info('built UI (path=%s)' % path)
576-
self.client.set_root_widget(self.main(*self.server.userdata))
586+
self.set_root_widget(self.main(*self.server.userdata))
577587
self._process_all(path)
578588
except:
579589
self._log.error('error processing GET request', exc_info=True)
@@ -600,7 +610,7 @@ def _process_all(self, func):
600610

601611
with self.update_lock:
602612
# render the HTML
603-
page_content = self.client.page.repr()
613+
page_content = self.page.repr()
604614

605615
self.wfile.write(encode_text("<!DOCTYPE html>\n"))
606616
self.wfile.write(encode_text(page_content))
@@ -660,7 +670,7 @@ def on_close(self):
660670
""" Called by the server when the App have to be terminated
661671
"""
662672
self._stop_update_flag = True
663-
for ws in self.client.websockets:
673+
for ws in self.websockets:
664674
ws.close()
665675

666676
def onload(self, emitter):

0 commit comments

Comments
 (0)