from __future__ import absolute_import, division, print_function, unicode_literals import glob import os, time, sys import flask from . import util, logger from flask_babel import gettext from shutil import copy, copyfile try: import configparser except ImportError: import ConfigParser as configparser if sys.version_info[0] < 3: import StringIO def list_cfg_files(self, path: str) -> list: """Generate list of config files. Args: path (str): Path to the config files. Returns: list: for every file a dict with keys for name, file, size, mdate, url. """ files = [] if path=="backup": cfg_path = os.path.join(self.get_plugin_data_folder(), "configs", "*") else: cfg_path = os.path.expanduser( self._settings.get(["configuration", "configpath"]) ) cfg_path = os.path.join(cfg_path, "*.cfg") cfg_files = glob.glob(cfg_path) logger.log_debug(self, "list_cfg_files Path: " + cfg_path) for f in cfg_files: filesize = os.path.getsize(f) filemdate = time.localtime(os.path.getmtime(f)) files.append(dict( name=os.path.basename(f), file=f, size=" ({:.1f} KB)".format(filesize / 1000.0), mdate=time.strftime("%d.%m.%Y %H:%M", filemdate), url= flask.url_for("index") + "plugin/klipper/download/" + os.path.basename(f), )) logger.log_debug(self, "list_cfg_files " + str(len(files)) + ": " + f) return files def get_cfg(self, file): """Get the content of a configuration file. Args: file (str): The name of the file to read Returns: dict: config (str): The configuration of the file text (str): The text of the error """ response = {"config":"", "text": ""} if not file: cfg_path = os.path.expanduser( self._settings.get(["configuration", "configpath"]) ) file = os.path.join(cfg_path, "printer.cfg") if util.file_exist(self, file): logger.log_debug(self, "get_cfg_files Path: " + file) try: with open(file, "r") as f: response['config'] = f.read() except IOError as Err: logger.log_error( self, "Error: Klipper config file not found at: {}".format(file) + "\n IOError: {}".format(Err) ) response['text'] = Err return response else: if sys.version_info[0] < 3: response['config'] = response.config.decode('utf-8') return response finally: f.close() else: response['text'] = gettext("File not found!") return response def save_cfg(self, content, filename="printer.cfg"): """Save the configuration file to given file. Args: content (str): The content of the configuration. filename (str): The filename of the configuration file. Default is "printer.cfg" Returns: bool: True if the configuration file was saved successfully. Otherwise False """ logger.log_debug( self, "Save klipper config" ) if sys.version_info[0] < 3: content = content.encode('utf-8') check_parse = self._settings.get(["configuration", "parse_check"]) logger.log_debug(self, "check_parse on filesave: {}".format(check_parse)) configpath = os.path.expanduser(self._settings.get(["configuration", "configpath"])) filepath = os.path.join(configpath, filename) logger.log_debug(self, "save filepath: {}".format(filepath)) self._settings.set(["configuration", "temp_config"], content) check = True if check_parse: check=check_cfg(self, content) if check == True: try: logger.log_debug(self, "Writing Klipper config to {}".format(filepath)) with open(filepath, "w") as f: f.write(content) except IOError: logger.log_error(self, "Error: Couldn't open Klipper config file: {}".format(filepath)) return False else: logger.log_debug(self, "Writen Klipper config to {}".format(filepath)) return True finally: f.close() copy_cfg_to_backup(self, filepath) else: return False def check_cfg(self, data): """Checks the given data on parsing errors. Args: data (str): Content to be validated. Returns: bool: True if the data is valid. False if it is not. """ try: dataToValidated = configparser.RawConfigParser(strict=False) if sys.version_info[0] < 3: import StringIO buf = StringIO.StringIO(data) dataToValidated.readfp(buf) else: dataToValidated.read_string(data) is_float_ok(self, dataToValidated) except configparser.Error as error: error.message = error.message.replace("\\n","") if sys.version_info[0] < 3: error.message = error.message.replace("file: u","Klipper Configuration", 1) error.message = error.message.replace("'","", 2) error.message = error.message.replace("u'","'", 1) else: error.message = error.message.replace("file:","Klipper Configuration", 1) error.message = error.message.replace("'","", 2) logger.log_error( self, "Error: Invalid Klipper config file:\n" + "{}".format(str(error)) ) util.send_message(self, "PopUp", "warning", "OctoKlipper: Invalid Config data\n", "\n" + str(error)) return False else: return True def is_float_ok(self, dataToValidated): sections_search_list = ["bltouch", "probe"] value_search_list = ["x_offset", "y_offset", "z_offset"] try: # cycle through sections and then values for y in sections_search_list: for x in value_search_list: if dataToValidated.has_option(y, x): a_float = dataToValidated.getfloat(y, x) except ValueError as error: logger.log_error( self, "Error: Invalid Value for " + x + " in Section: " + y + "\n" + "{}".format(str(error)) ) util.send_message( self, "PopUp", "warning", "OctoKlipper: Invalid Config data\n", "\n" + "Invalid Value for " + x + " in Section: " + y + "\n" + "{}".format(str(error)) ) return False else: return True def copy_cfg(self, file, dst): """Copy the config file to the destination. Args: file (str): Filepath of the config file to copy. dst (str): Path to copy the config file to. Returns: bool: True if the copy succeeded, False otherwise. """ if os.path.isfile(file): try: copy(file, dst) except IOError: logger.log_error( self, "Error: Klipper config file not found at: {}".format(file) ) return False else: logger.log_debug( self, "File copied: " + file ) return True return False def copy_cfg_to_backup(self, src): """Copy the config file to backup directory of OctoKlipper. Args: src (str): Path to the config file to copy. Returns: bool: True if the config file was copied successfully. False otherwise. """ if not os.path.isfile(src): return False cfg_path = os.path.join(self.get_plugin_data_folder(), "configs", "") filename = os.path.basename(src) if not os.path.exists(cfg_path): try: os.mkdir(cfg_path) except OSError: logger.log_error(self, "Error: Creation of the backup directory {} failed".format(cfg_path)) return False else: logger.log_debug(self, "Directory {} created".format(cfg_path)) dst = os.path.join(cfg_path, filename) logger.log_debug(self, "copy_cfg_to_backup:" + src + " to " + dst) if src == dst: return False try: copyfile(src, dst) except IOError: logger.log_error( self, "Error: Couldn't copy Klipper config file to {}".format(dst) ) return False else: logger.log_debug(self, "CfgBackup " + dst + " writen") return True