From cbdf85c27ab431e75bb20dc561842996164b2421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 1 Jun 2017 12:10:12 +0200 Subject: [PATCH] Fix crash on startup thanks to invalid default profile & auto connect See #1942 This does NOT fix the root cause of `_default.profile` becoming an empty file (apparently during migration from config.yaml?), however since this particular situation was impossible to reproduce so far this workaround for the consequences will have to suffice for now since we want a hotfix as fast as possible for 1.3.3. --- src/octoprint/printer/profile.py | 32 ++++++++++++++++++++++++++++++-- src/octoprint/server/__init__.py | 13 ++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/octoprint/printer/profile.py b/src/octoprint/printer/profile.py index 5b3f4b48..fb9493c6 100644 --- a/src/octoprint/printer/profile.py +++ b/src/octoprint/printer/profile.py @@ -215,12 +215,18 @@ class PrinterProfileManager(object): if self.exists("_default"): return + if not isinstance(default_overrides, dict): + self._logger.warn("Existing default profile from settings is not a valid profile, refusing to migrate: {!r}".format(default_overrides)) + return + default_overrides["id"] = "_default" self.save(default_overrides) settings().set(["printerProfiles", "defaultProfile"], None) settings().save() + self._logger.info("Migrated default printer profile from settings to _default.profile: {!r}".format(default_overrides)) + def _verify_default_available(self): default_id = settings().get(["printerProfile", "default"]) if default_id is None: @@ -228,12 +234,23 @@ class PrinterProfileManager(object): 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)) + if default_id == "_default": + self._logger.error("Profile _default does not exist, creating _default again and setting it as default") + else: + 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() + default_id = "_default" + + profile = self.get(default_id) + if profile is None: + self._logger.error("Selected default profile {} is invalid, resetting to default values".format(default_id)) + profile = copy.deepcopy(self.__class__.default) + profile["id"] = default_id + self.save(self.__class__.default, allow_overwrite=True, make_default=True) def select(self, identifier): if identifier is None or not self.exists(identifier): @@ -241,7 +258,12 @@ class PrinterProfileManager(object): return False else: self._current = self.get(identifier) - return True + if self._current is None: + self._logger.error("Profile {} is invalid, cannot select, falling back to default".format(identifier)) + self._current = self.get_default() + return False + else: + return True def deselect(self): self._current = None @@ -310,6 +332,8 @@ class PrinterProfileManager(object): profile = self.get(default) if profile is not None: return profile + else: + self._logger.warn("Default profile {} is invalid, falling back to built-in defaults".format(default)) return copy.deepcopy(self.__class__.default) @@ -344,6 +368,7 @@ class PrinterProfileManager(object): try: profile = self._load_from_path(path) except InvalidProfileError: + self._logger.warn("Profile {} is invalid, skipping".format(identifier)) continue if profile is None: @@ -373,6 +398,9 @@ class PrinterProfileManager(object): with open(path) as f: profile = yaml.safe_load(f) + if profile is None or not isinstance(profile, dict): + raise InvalidProfileError("Profile is None or not a dictionary") + if self._migrate_profile(profile): try: self._save_to_path(path, profile, allow_overwrite=True) diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index 20397ef7..94b9bab5 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -475,11 +475,14 @@ class Server(object): # auto connect if self._settings.getBoolean(["serial", "autoconnect"]): - (port, baudrate) = self._settings.get(["serial", "port"]), self._settings.getInt(["serial", "baudrate"]) - printer_profile = printerProfileManager.get_default() - connectionOptions = printer.__class__.get_connection_options() - if port in connectionOptions["ports"]: - printer.connect(port=port, baudrate=baudrate, profile=printer_profile["id"] if "id" in printer_profile else "_default") + try: + (port, baudrate) = self._settings.get(["serial", "port"]), self._settings.getInt(["serial", "baudrate"]) + printer_profile = printerProfileManager.get_default() + connectionOptions = printer.__class__.get_connection_options() + if port in connectionOptions["ports"]: + printer.connect(port=port, baudrate=baudrate, profile=printer_profile["id"] if "id" in printer_profile else "_default") + except: + self._logger.exception("Something went wrong while attempting to automatically connect to the printer") # start up watchdogs if self._settings.getBoolean(["feature", "pollWatched"]):