Skip to content

Commit

Permalink
Fix crash on startup thanks to invalid default profile & auto connect
Browse files Browse the repository at this point in the history
See OctoPrint#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.
  • Loading branch information
foosel committed Jun 1, 2017
1 parent b55c4ef commit cbdf85c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
32 changes: 30 additions & 2 deletions src/octoprint/printer/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,33 +215,55 @@ def _migrate_old_default_profile(self):
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:
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))
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):
self._current = self.get_default()
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
Expand Down Expand Up @@ -310,6 +332,8 @@ def get_default(self):
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)

Expand Down Expand Up @@ -344,6 +368,7 @@ def _load_all(self):
try:
profile = self._load_from_path(path)
except InvalidProfileError:
self._logger.warn("Profile {} is invalid, skipping".format(identifier))
continue

if profile is None:
Expand Down Expand Up @@ -373,6 +398,9 @@ def _load_from_path(self, path):
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)
Expand Down
13 changes: 8 additions & 5 deletions src/octoprint/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,14 @@ def joined_dict(*dicts):

# 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"]):
Expand Down

0 comments on commit cbdf85c

Please sign in to comment.