diff --git a/src/octoprint/printer/profile.py b/src/octoprint/printer/profile.py index 15610a88..5b3f4b48 100644 --- a/src/octoprint/printer/profile.py +++ b/src/octoprint/printer/profile.py @@ -204,6 +204,37 @@ class PrinterProfileManager(object): self._folder = settings().getBaseFolder("printerProfiles") self._logger = logging.getLogger(__name__) + self._migrate_old_default_profile() + self._verify_default_available() + + def _migrate_old_default_profile(self): + default_overrides = settings().get(["printerProfiles", "defaultProfile"]) + if not default_overrides: + return + + if self.exists("_default"): + return + + default_overrides["id"] = "_default" + self.save(default_overrides) + + settings().set(["printerProfiles", "defaultProfile"], None) + settings().save() + + def _verify_default_available(self): + default_id = settings().get(["printerProfile", "default"]) + if default_id is None: + default_id = "_default" + + if not self.exists(default_id): + if not self.exists("_default"): + self._logger.error("Selected default profile {} and _default do not exist, creating _default again and setting it as default".format(default_id)) + self.save(self.__class__.default, allow_overwrite=True, make_default=True) + else: + self._logger.error("Selected default profile {} does not exists, resetting to _default".format(default_id)) + settings().set(["printerProfiles", "default"], "_default") + settings().save() + def select(self, identifier): if identifier is None or not self.exists(identifier): self._current = self.get_default() @@ -220,9 +251,7 @@ class PrinterProfileManager(object): def get(self, identifier): try: - if identifier == "_default": - return self._load_default() - elif self.exists(identifier): + if self.exists(identifier): return self._load_from_path(self._get_profile_path(identifier)) else: return None @@ -230,10 +259,10 @@ class PrinterProfileManager(object): return None def remove(self, identifier): - if identifier == "_default": - return False if self._current is not None and self._current["id"] == identifier: return False + elif settings().get(["printerProfiles", "default"]) == identifier: + return False return self._remove_from_path(self._get_profile_path(identifier)) def save(self, profile, allow_overwrite=False, make_default=False): @@ -246,21 +275,16 @@ class PrinterProfileManager(object): identifier = self._sanitize(identifier) profile["id"] = identifier + + self._migrate_profile(profile) profile = dict_sanitize(profile, self.__class__.default) + profile = dict_merge(self.__class__.default, profile) - if identifier == self.__class__.default["id"]: - default_profile = dict_merge(self._load_default(), profile) - if not self._ensure_valid_profile(default_profile): - raise InvalidProfileError() + self._save_to_path(self._get_profile_path(identifier), profile, allow_overwrite=allow_overwrite) - settings().set(["printerProfiles", "defaultProfile"], default_profile, defaults=dict(printerProfiles=dict(defaultProfile=self.__class__.default))) + if make_default: + settings().set(["printerProfiles", "default"], identifier) settings().save() - else: - self._save_to_path(self._get_profile_path(identifier), profile, allow_overwrite=allow_overwrite) - - if make_default: - settings().set(["printerProfiles", "default"], identifier) - settings().save() if self._current is not None and self._current["id"] == identifier: self.select(identifier) @@ -268,8 +292,7 @@ class PrinterProfileManager(object): def is_default_unmodified(self): default = settings().get(["printerProfiles", "default"]) - default_overrides = settings().get(["printerProfiles", "defaultProfile"]) - return (default is None or default == self.__class__.default["id"]) and not default_overrides + return default is None or default == "_default" or not self.exists("_default") @property def profile_count(self): @@ -288,7 +311,7 @@ class PrinterProfileManager(object): if profile is not None: return profile - return self._load_default() + return copy.deepcopy(self.__class__.default) def set_default(self, identifier): all_identifiers = self._load_all_identifiers().keys() @@ -310,8 +333,6 @@ class PrinterProfileManager(object): def exists(self, identifier): if identifier is None: return False - elif identifier == "_default": - return True else: path = self._get_profile_path(identifier) return os.path.exists(path) and os.path.isfile(path) @@ -321,23 +342,20 @@ class PrinterProfileManager(object): results = dict() for identifier, path in all_identifiers.items(): try: - if identifier == "_default": - profile = self._load_default() - else: - profile = self._load_from_path(path) + profile = self._load_from_path(path) except InvalidProfileError: continue if profile is None: continue - results[identifier] = dict_merge(self._load_default(), profile) + results[identifier] = dict_merge(self.__class__.default, profile) return results def _load_all_identifiers(self): - results = dict(_default=None) + results = dict() for entry in scandir(self._folder): - if is_hidden_path(entry.name) or not entry.name.endswith(".profile") or entry.name == "_default.profile": + if is_hidden_path(entry.name) or not entry.name.endswith(".profile"): continue if not entry.is_file(): @@ -369,8 +387,6 @@ class PrinterProfileManager(object): return profile def _save_to_path(self, path, profile, allow_overwrite=False): - self._migrate_profile(profile) - profile = dict_merge(self.__class__.default, profile) validated_profile = self._ensure_valid_profile(profile) if not validated_profile: raise InvalidProfileError() @@ -394,21 +410,6 @@ class PrinterProfileManager(object): except: return False - def _load_default(self): - default_overrides = settings().get(["printerProfiles", "defaultProfile"]) - if self._migrate_profile(default_overrides): - try: - settings().set(["printerProfiles", "defaultProfile"], default_overrides) - settings().save() - except: - self._logger.exception("Tried to save default profile after migrating it while loading, ran into exception") - - profile = self._ensure_valid_profile(dict_merge(copy.deepcopy(self.__class__.default), default_overrides)) - if not profile: - self._logger.warn("Invalid default profile after applying overrides") - return copy.deepcopy(self.__class__.default) - return profile - def _get_profile_path(self, identifier): return os.path.join(self._folder, "%s.profile" % identifier) diff --git a/src/octoprint/server/api/printer_profiles.py b/src/octoprint/server/api/printer_profiles.py index bc9f6f2c..7b286f31 100644 --- a/src/octoprint/server/api/printer_profiles.py +++ b/src/octoprint/server/api/printer_profiles.py @@ -105,8 +105,14 @@ def printerProfilesGet(identifier): @api.route("/printerprofiles/", methods=["DELETE"]) @restricted_access def printerProfilesDelete(identifier): - if printerProfileManager.get_current_or_default()["id"] == identifier: - return make_response("Cannot delete currently selected profile: %s" % identifier, 409) + current_profile = printerProfileManager.get_current() + if current_profile and current_profile["id"] == identifier: + return make_response("Cannot delete currently selected profile: {}".format(identifier), 409) + + default_profile = printerProfileManager.get_default() + if default_profile and default_profile["id"] == identifier: + return make_response("Cannot delete default profile: {}".format(identifier), 409) + printerProfileManager.remove(identifier) return NO_CONTENT diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index 7469dfef..5081459c 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -229,8 +229,7 @@ default_settings = { "cutoff": 30 }, "printerProfiles": { - "default": None, - "defaultProfile": {} + "default": None }, "printerParameters": { "pauseTriggers": [],