OctoprintKlipperPlugin/octoprint_klipper/cfgUtils.py

298 lines
8.8 KiB
Python
Raw Normal View History

2021-09-05 16:28:57 +03:00
from __future__ import absolute_import, division, print_function, unicode_literals
import glob
import os, time, sys
2021-09-05 17:51:52 +03:00
import flask
2021-09-05 16:28:57 +03:00
from . import util, logger
from flask_babel import gettext
2021-09-05 17:51:52 +03:00
from shutil import copy, copyfile
try:
import configparser
except ImportError:
import ConfigParser as configparser
if sys.version_info[0] < 3:
import StringIO
2021-09-05 16:28:57 +03:00
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))
if path != "backup":
url = flask.url_for("index") + "plugin/klipper/download/configs/" + os.path.basename(f)
else:
url = flask.url_for("index") + "plugin/klipper/download/backup/" + os.path.basename(f)
2021-09-05 16:28:57 +03:00
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= url,
2021-09-05 16:28:57 +03:00
))
2021-09-05 17:51:52 +03:00
logger.log_debug(self, "list_cfg_files " + str(len(files)) + ": " + f)
2021-09-05 16:28:57 +03:00
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')
2021-09-05 16:28:57 +03:00
configpath = os.path.expanduser(self._settings.get(["configuration", "configpath"]))
if filename[-4:] != ".cfg":
filename += ".cfg"
2021-09-05 16:28:57 +03:00
filepath = os.path.join(configpath, filename)
logger.log_debug(self, "save filepath: {}".format(filepath))
self._settings.set(["configuration", "temp_config"], content)
check_parse = self._settings.get(["configuration", "parse_check"])
logger.log_debug(self, "check_parse on filesave: {}".format(check_parse))
if check_parse and not check_cfg(self, content):
return False
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))
2021-09-05 16:28:57 +03:00
return False
else:
logger.log_debug(self, "Writen Klipper config to {}".format(filepath))
return True
finally:
f.close()
copy_cfg_to_backup(self, filepath)
2021-09-05 16:28:57 +03:00
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)
except configparser.Error as error:
show_error_message(self, error)
logger.log_debug(self, 'check_cfg: NOK!')
2021-09-05 16:28:57 +03:00
return False
else:
if not is_float_ok(self, dataToValidated):
logger.log_debug(self, "check_cfg: NOK!")
return False
logger.log_debug(self, "check_cfg: OK")
2021-09-05 16:28:57 +03:00
return True
def show_error_message(self, 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', 'Invalid Config data\n', ('\n' + str(error))
)
2021-09-05 17:51:52 +03:00
def is_float_ok(self, dataToValidated):
sections_search_list = [
"bltouch",
"probe"
]
value_search_list = [
"x_offset",
"y_offset",
"z_offset"
]
2021-09-05 17:51:52 +03:00
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 <b>" + x + "</b> in Section: <b>" + y + "</b>\n"
+ "{}".format(str(error))
)
util.send_message(
self,
"PopUp",
"warning",
"Invalid Config data\n",
2021-09-05 17:51:52 +03:00
"\n"
+ "Invalid Value for <b>" + x + "</b> in Section: <b>" + y + "</b>\n"
+ "{}".format(str(error))
)
return False
else:
return True
2021-09-05 16:28:57 +03:00
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.
"""
2021-09-05 17:51:52 +03:00
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))
2021-09-05 16:28:57 +03:00
return False
2021-09-05 17:51:52 +03:00
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:
2021-09-05 16:28:57 +03:00
return False
2021-09-05 17:51:52 +03:00
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
2021-09-05 16:28:57 +03:00