From 939e92de6241906bdfd39b51552079855af2eaf5 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Fri, 4 Nov 2016 20:19:12 +0800 Subject: webui: websocket.py: Implement "set" action for "_handle_configs()" Finish the "_set_configs()" function to implement the "set" action for "_handle_configs()". Also change the "status" keyword to "success" to be more intuitive. --- fg21sim/configs/manager.py | 10 +++++----- fg21sim/webui/websocket.py | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/fg21sim/configs/manager.py b/fg21sim/configs/manager.py index 0809126..b19978b 100644 --- a/fg21sim/configs/manager.py +++ b/fg21sim/configs/manager.py @@ -337,7 +337,7 @@ class ConfigManager: val_new = reduce(operator.getitem, key, config_new) d2 = reduce(lambda x, y: {y: x}, reversed(key), val_new) self.merge(d2) - logger.info("Set config: {key}: {val_new} <= {val_old}".format( + logger.info("Set config: {key}: {val_new} <- {val_old}".format( key="/".join(key), val_new=val_new, val_old=val_old)) def get_path(self, key): @@ -364,9 +364,9 @@ class ConfigManager: NOTE ---- - - The "~" (tilde) inside path is expanded to the user home directory. + - The beginning ``~`` (tilde) is expanded to user's home directory. - The relative path (with respect to the user configuration file) - is converted to absolute path if `self.userconfig` presents. + is converted to absolute path if ``self.userconfig`` is valid. """ value = self.getn(key) if value is None: @@ -379,8 +379,8 @@ class ConfigManager: # path = os.path.expanduser(value) if not os.path.isabs(path): - # Got relative path, try to convert to the absolute path - if hasattr(self, "userconfig"): + # Got a relative path, try to convert to the absolute path + if self.userconfig is not None: # User configuration loaded path = os.path.join(os.path.dirname(self.userconfig), path) else: diff --git a/fg21sim/webui/websocket.py b/fg21sim/webui/websocket.py index 76258a4..1e9b9d6 100644 --- a/fg21sim/webui/websocket.py +++ b/fg21sim/webui/websocket.py @@ -17,6 +17,7 @@ References http://caniuse.com/#feat=websockets """ +import os import json import logging @@ -117,7 +118,7 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): The sent message also has a ``type`` item of same value, which the client can be used to figure out the proper actions. - There is a ``status`` item which indicates the status of the + There is a ``success`` item which indicates the status of the requested operation, and a ``data`` item containing the response data. """ @@ -128,10 +129,10 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): except json.JSONDecodeError: logger.warning("WebSocket: {0}: ".format(self.name) + "message is not a valid JSON string") - response = {"status": False, "type": None} + response = {"success": False, "type": None} except (KeyError, TypeError): logger.warning("WebSocket: %s: skip invalid message" % self.name) - response = {"status": False, "type": None} + response = {"success": False, "type": None} else: # Check the message type and dispatch task if msg_type == "configs": @@ -147,7 +148,7 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): # Message of unknown type logger.warning("WebSocket: {0}: ".format(self.name) + "unknown message type: {0}".format(msg_type)) - response = {"status": False, "type": msg_type} + response = {"success": False, "type": msg_type} # msg_response = json.dumps(response) self.write_message(msg_response) @@ -189,24 +190,24 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): if msg_action == "get": # Get the values of the specified options data, errors = self._get_configs(keys=msg_data) - response["status"] = True if errors == {} else False + response["success"] = True if errors == {} else False response["data"] = data response["errors"] = errors elif msg_action == "set": # Set the values of the specified options errors = self._set_configs(data=msg_data) - response["status"] = True if errors == {} else False + response["success"] = True if errors == {} else False response["data"] = {} response["errors"] = errors else: logger.warning("WebSocket: {0}: ".format(self.name) + "unknown action: {0}".format(msg_action)) - response["status"] = False + response["success"] = False response["data"] = {} response["errors"] = {} except KeyError: # Received message has wrong syntax/format - response = {"status": False, "type": msg_type, "action": None} + response = {"success": False, "type": msg_type, "action": None} # logger.debug("WebSocket: {0}: ".format(self.name) + "response: {0}".format(response)) @@ -264,6 +265,10 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): A dictionary of key-value pairs, with keys specifying the config options whose value will be changed, and values the new values to which config options will be set. + NOTE: + If want to set the ``userconfig`` option, an *absolute path* + must be provided (i.e., client should take care of the ``workdir`` + value and generate a absolute path for ``userconfig``). Returns ------- @@ -271,14 +276,32 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): When error occurs (e.g., invalid key, invalid values), then the specific errors with details are stored in this dictionary. """ - pass + errors = {} + for key, value in data.items(): + if key == "userconfig": + # NOTE: The ``userconfig`` must be an absolute path + if os.path.isabs(value): + self.configs.userconfig = value + else: + errors["userconfig"] = "Not an absolute path" + else: + try: + self.configs.setn(key, value) + except KeyError as e: + errors[key] = str(e) + # NOTE: + # Check the whole configurations after all provided options are + # updated, and merge the validation errors. + __, cherr = self.configs.check_all(raise_exception=False) + errors.update(cherr) + return errors def _handle_console(self, msg): # Got a message of supported types msg_type = msg["type"] logger.info("WebSocket: {0}: ".format(self.name) + "handle message of type: {0}".format(msg_type)) - response = {"status": True, "type": msg_type} + response = {"success": True, "type": msg_type} return response def _handle_results(self, msg): @@ -286,5 +309,5 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): msg_type = msg["type"] logger.info("WebSocket: {0}: ".format(self.name) + "handle message of type: {0}".format(msg_type)) - response = {"status": True, "type": msg_type} + response = {"success": True, "type": msg_type} return response -- cgit v1.2.2