302 lines
8.7 KiB
Python
302 lines
8.7 KiB
Python
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
import glob
|
|
import os, time, sys
|
|
import io
|
|
import flask
|
|
|
|
from octoprint_klipper.util import *
|
|
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):
|
|
"""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", "config_path"])
|
|
)
|
|
cfg_path = os.path.join(cfg_path, "*.cfg")
|
|
cfg_files = glob.glob(cfg_path)
|
|
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)
|
|
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,
|
|
))
|
|
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, self._settings.get(["configuration", "baseconfig"]))
|
|
if file_exist(self, file):
|
|
log_debug(self, "get_cfg_files Path: " + file)
|
|
try:
|
|
with io.open(file, "r", encoding='utf-8') as f:
|
|
response['config'] = f.read()
|
|
except IOError as Err:
|
|
log_error(
|
|
self,
|
|
gettext("Error: Klipper config file not found at:")
|
|
+ " {}".format(file)
|
|
+ "\n"
|
|
+ gettext("IOError:") + " {}".format(Err)
|
|
)
|
|
response['text'] = Err
|
|
return response
|
|
except UnicodeDecodeError as Err:
|
|
log_error(
|
|
self,
|
|
gettext("Decode Error:")
|
|
+"\n"
|
|
+ "{}".format(Err)
|
|
+ "\n\n"
|
|
+ gettext("Please convert your config files to utf-8!")
|
|
+ "\n"
|
|
+ gettext("Or you can also paste your config \ninto the Editor and save it.")
|
|
)
|
|
response['text'] = Err
|
|
return response
|
|
else:
|
|
return response
|
|
else:
|
|
response['text'] = gettext("File not found!")
|
|
return response
|
|
|
|
|
|
def save_cfg(self, content, filename):
|
|
"""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
|
|
"""
|
|
|
|
log_debug(
|
|
self,
|
|
"Save klipper config"
|
|
)
|
|
|
|
|
|
configpath = os.path.expanduser(self._settings.get(["configuration", "config_path"]))
|
|
if filename == "":
|
|
filename = self._settings.get(["configuration", "baseconfig"])
|
|
if filename[-4:] != ".cfg":
|
|
filename += ".cfg"
|
|
|
|
filepath = os.path.join(configpath, filename)
|
|
|
|
log_debug(self, "Writing Klipper config to {}".format(filepath))
|
|
try:
|
|
with io.open(filepath, "w", encoding='utf-8') as f:
|
|
f.write(content)
|
|
except IOError:
|
|
log_error(self, "Error: Couldn't open Klipper config file: {}".format(filepath))
|
|
return False
|
|
else:
|
|
log_debug(self, "Written Klipper config to {}".format(filepath))
|
|
return True
|
|
finally:
|
|
copy_cfg_to_backup(self, filepath)
|
|
|
|
|
|
def check_cfg_ok(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)
|
|
log_debug(self, 'check_cfg: NOK!')
|
|
return False
|
|
else:
|
|
if not is_float_ok(self, dataToValidated):
|
|
log_debug(self, "check_cfg: NOK!")
|
|
return False
|
|
log_debug(self, "check_cfg: OK")
|
|
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)
|
|
log_error(
|
|
self,
|
|
('Error: Invalid Klipper config file:\n' + '{}'.format(str(error))),
|
|
)
|
|
|
|
|
|
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:
|
|
log_error(
|
|
self,
|
|
"Error: Invalid Value for <b>" + x + "</b> in Section: <b>" + y + "</b>\n"
|
|
+ "{}".format(str(error))
|
|
)
|
|
send_message(
|
|
self,
|
|
type = "PopUp",
|
|
subtype = "warning",
|
|
title = "Invalid Config data\n",
|
|
payload = "\n"
|
|
+ "Invalid Value for <b>" + x + "</b> in Section: <b>" + y + "</b>\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:
|
|
log_error(
|
|
self,
|
|
"Error: Klipper config file not found at: {}".format(file)
|
|
)
|
|
return False
|
|
else:
|
|
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:
|
|
log_error(self, "Error: Creation of the backup directory {} failed".format(cfg_path))
|
|
return False
|
|
else:
|
|
log_debug(self, "Directory {} created".format(cfg_path))
|
|
|
|
dst = os.path.join(cfg_path, filename)
|
|
log_debug(self, "copy_cfg_to_backup:" + src + " to " + dst)
|
|
if src == dst:
|
|
return False
|
|
try:
|
|
copyfile(src, dst)
|
|
except IOError:
|
|
log_error(
|
|
self,
|
|
"Error: Couldn't copy Klipper config file to {}".format(dst)
|
|
)
|
|
return False
|
|
else:
|
|
log_debug(self, "CfgBackup " + dst + " written")
|
|
return True
|