From f6bf46fa19abb546f0c3bf92f769b9b3a5637844 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Sat, 5 Nov 2016 09:57:29 +0800 Subject: webui: websocket.py: Support "reset", "load", "save" actions. * Improve the response data to be more consistent. If the request failed, the returned response has "success" item of value "False" and an "error" item recording the message; * Add method "_reset_configs()" to handle the "reset" action; * Add method "_load_configs()" to handle the "load" action; * Add method "_save_configs()" to handle the "save" action. NOTE: needs tests. --- fg21sim/webui/websocket.py | 123 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 18 deletions(-) (limited to 'fg21sim') diff --git a/fg21sim/webui/websocket.py b/fg21sim/webui/websocket.py index a441272..23a4423 100644 --- a/fg21sim/webui/websocket.py +++ b/fg21sim/webui/websocket.py @@ -24,6 +24,7 @@ import logging import tornado.websocket from ..configs import ConfigManager +from ..errors import ConfigError from .utils import get_host_ip @@ -189,28 +190,54 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): try: msg_type = msg["type"] msg_action = msg["action"] - msg_data = msg["data"] response = {"type": msg_type, "action": msg_action} logger.info("WebSocket: {0}: handle message: ".format(self.name) + "type: {0}, action: {1}".format(msg_type, msg_action)) if msg_action == "get": # Get the values of the specified options - data, errors = self._get_configs(keys=msg_data) - response["success"] = True - response["data"] = data - response["errors"] = errors + try: + data, errors = self._get_configs(keys=msg["data"]) + response["success"] = True + response["data"] = data + response["errors"] = errors + except KeyError: + response["success"] = False + response["error"] = "'data' is missing" elif msg_action == "set": # Set the values of the specified options - errors = self._set_configs(data=msg_data) - response["success"] = True - response["data"] = {} # be more consistent - response["errors"] = errors + try: + errors = self._set_configs(data=msg["data"]) + response["success"] = True + response["data"] = {} # be more consistent + response["errors"] = errors + except KeyError: + response["success"] = False + response["error"] = "'data' is missing" elif msg_action == "reset": - raise NotImplementedError("TODO") + # Reset the configurations to the defaults + self._reset_configs() + response["success"] = True elif msg_action == "load": - raise NotImplementedError("TODO") + # Load the supplied user configuration file + try: + success, error = self._load_configs(msg["userconfig"]) + response["success"] = success + if not success: + response["error"] = error + except KeyError: + response["success"] = False + response["error"] = "'userconfig' is missing" elif msg_action == "save": - raise NotImplementedError("TODO") + # Save current configurations to file + try: + success, error = self._save_configs(msg["outfile"], + msg["clobber"]) + response["success"] = success + if not success: + response["error"] = error + except KeyError: + response["success"] = False + response["error"] = "'outfile' or 'clobber' is missing" else: logger.warning("WebSocket: {0}: ".format(self.name) + "unknown action: {0}".format(msg_action)) @@ -272,6 +299,10 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): """Set the values of the config options specified by the given keys to the corresponding supplied data. + NOTE + ---- + The ``userconfig`` and ``workdir`` options are ignored. + Parameters ---------- data : dict @@ -291,12 +322,9 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): """ 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" + if key in ["userconfig", "workdir"]: + # Ignore "userconfig" and "workdir" + continue else: try: self.configs.setn(key, value) @@ -309,6 +337,65 @@ class FG21simWSHandler(tornado.websocket.WebSocketHandler): errors.update(cherr) return errors + def _reset_configs(self): + """Reset the configurations to the defaults.""" + self.configs.reset() + + def _load_configs(self, userconfig): + """Load configurations from the provided user configuration file. + + Parameters + ---------- + userconfig: str + The filepath to the user configuration file, which must be + an *absolute path*. + + Returns + ------- + success : bool + ``True`` if the operation succeeded, otherwise, ``False``. + error : str + If failed, this ``error`` saves the details, otherwise, ``None``. + """ + success = False + error = None + if os.path.isabs(userconfig): + try: + self.configs.read_userconfig(userconfig) + success = True + except ConfigError as e: + error = str(e) + else: + error = "Not an absolute path" + return (success, error) + + def _save_configs(self, outfile, clobber=False): + """Save current configurations to file. + + Parameters + ---------- + outfile: str + The filepath to the output configuration file, which must be + an *absolute path*. + clobber : bool, optional + Whether overwrite the output file if already exists? + + Returns + ------- + success : bool + ``True`` if the operation succeeded, otherwise, ``False``. + error : str + If failed, this ``error`` saves the details, otherwise, ``None``. + """ + success = False + error = None + try: + self.configs.save(outfile, clobber=clobber) + success = True + except (ValueError, OSError) as e: + error = str(e) + return (success, error) + def _handle_console(self, msg): # Got a message of supported types msg_type = msg["type"] -- cgit v1.2.2