Skip to content

Commit

Permalink
Move autosaved data to dedicated config file
Browse files Browse the repository at this point in the history
Autosaved data is instead saved to a *.autosave.cfg config file, which
is automatically loaded along it's associated main *.cfg file.

The goal is to eventually no longer modify user-authored configuration
automatically, so that it can't introduce unintended changes. This will
also allow proper version control of config files without producing
unnecessarily noisy diffs.

Autosaved data will keep being read from both embedded and dedicated
sources, but the SAVE_CONFIG command will only write the dedicated
file from now on. This maintains backwards-compatibility, while
gradually migrating existing autosaved settings to the *.autosave.cfg
file whenever the command keeps being used.

This is just the first step in a bigger migration process, and
therefore still requires some automated changes to the user config
files at the moment. However, this will reduce the necessary changes,
and is only required while the embedded autosave system is still
supported.
  • Loading branch information
jwueller committed Dec 21, 2024
1 parent ec8edf3 commit 5e8baef
Showing 1 changed file with 34 additions and 12 deletions.
46 changes: 34 additions & 12 deletions klippy/configfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,17 @@ def __init__(self, printer):
def get_printer(self):
return self.printer

def _read_config_file_silent(self, filename):
with open(filename, "r") as f:
return f.read().replace("\r\n", "\n")

def _read_config_file(self, filename):
try:
f = open(filename, "r")
data = f.read()
f.close()
return self._read_config_file_silent(filename)
except:
msg = "Unable to open config file %s" % (filename,)
logging.exception(msg)
raise error(msg)
return data.replace("\r\n", "\n")

def _find_autosave_data(self, data):
regular_data = data
Expand Down Expand Up @@ -472,10 +473,27 @@ def read_config(self, filename):
self._read_config_file(filename), filename
)

def _build_autosave_filename(self, filename):
directory, name = os.path.split(filename)
base, ext = os.path.splitext(name)
return os.path.join(directory, base + ".autosave" + ext)

def read_main_config(self):
filename = self.printer.get_start_args()["config_file"]
data = self._read_config_file(filename)
regular_data, autosave_data = self._find_autosave_data(data)

# Autosave data used to get written straight into the user's main config
# file. This was very invasive, so we now write all autosave data into a
# separate file, which is then loaded implicitly with the main config.
# However, we still have to read existing autosave data in the main
# config file to remain backwards-compatible.
regular_data, autosave_data = self._find_autosave_data(
self._read_config_file(filename))
try:
autosave_data = self._read_config_file_silent(
self._build_autosave_filename(filename)) + "\n" + autosave_data
except FileNotFoundError:
pass # optional

regular_config = self._build_config_wrapper(regular_data, filename)
autosave_data = self._strip_duplicates(autosave_data, regular_config)
self.autosave = self._build_config_wrapper(autosave_data, filename)
Expand Down Expand Up @@ -726,11 +744,8 @@ def cmd_SAVE_CONFIG(self, gcmd):
return
gcode = self.printer.lookup_object("gcode")
# Create string containing autosave data
autosave_data = self._build_config_string(self.autosave)
lines = [("#*# " + l).strip() for l in autosave_data.split("\n")]
lines.insert(0, "\n" + AUTOSAVE_HEADER.rstrip())
lines.append("")
autosave_data = "\n".join(lines)
autosave_data = (AUTOSAVE_HEADER.rstrip() + "\n\n"
+ self._build_config_string(self.autosave))
# Read in and validate current config file
cfgname = self.printer.get_start_args()["config_file"]
try:
Expand All @@ -748,9 +763,16 @@ def cmd_SAVE_CONFIG(self, gcmd):

# NOW we're safe to check for conflicts
self._disallow_include_conflicts(regular_data, cfgname, gcode)
data = regular_data.rstrip() + autosave_data
data = regular_data.rstrip()
self._write_backup(cfgname, data, gcode)

# Eventually we would want to stop touching the user config at all and
# only write autosave data independently, but for as long as we support
# auto-migration from embedded autosave data, we have to keep fixing up
# those user configs. See config loading for more info.
with open(self._build_autosave_filename(cfgname), "w+") as f:
f.write(autosave_data)

# If requested restart or no restart just flag config saved
require_restart = gcmd.get_int("RESTART", 1, minval=0, maxval=1)
if require_restart:
Expand Down

0 comments on commit 5e8baef

Please sign in to comment.