Catch ContainerFormatError when deserialising containers

Only the deserialize() functions themselves may pass the ContainerFormatError on, because their callers will have to handle those errors anyway.

Contributes to issue CURA-5045.
This commit is contained in:
Ghostkeeper 2018-04-06 13:26:16 +02:00
parent c9dc429b2b
commit 572721e20d
No known key found for this signature in database
GPG key ID: 5252B696FB5E7C7A
6 changed files with 48 additions and 23 deletions

View file

@ -1,4 +1,4 @@
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import os.path import os.path
@ -22,12 +22,10 @@ from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
from UM.MimeTypeDatabase import MimeTypeNotFoundError from UM.MimeTypeDatabase import MimeTypeNotFoundError
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.i18n import i18nCatalog
from cura.Settings.ExtruderManager import ExtruderManager from cura.Settings.ExtruderManager import ExtruderManager
from cura.Settings.ExtruderStack import ExtruderStack from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -289,7 +287,9 @@ class ContainerManager(QObject):
with open(file_url, "rt", encoding = "utf-8") as f: with open(file_url, "rt", encoding = "utf-8") as f:
container.deserialize(f.read()) container.deserialize(f.read())
except PermissionError: except PermissionError:
return {"status": "error", "message": "Permission denied when trying to read the file"} return {"status": "error", "message": "Permission denied when trying to read the file."}
except ContainerFormatError:
return {"status": "error", "Message": "The material file appears to be corrupt."}
except Exception as ex: except Exception as ex:
return {"status": "error", "message": str(ex)} return {"status": "error", "message": str(ex)}

View file

@ -1,4 +1,4 @@
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import os import os
@ -11,6 +11,7 @@ from typing import Optional
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from UM.Decorators import override from UM.Decorators import override
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Settings.ContainerStack import ContainerStack from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
@ -25,7 +26,6 @@ from UM.Resources import Resources
from . import ExtruderStack from . import ExtruderStack
from . import GlobalStack from . import GlobalStack
from .ExtruderManager import ExtruderManager
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
@ -420,7 +420,6 @@ class CuraContainerRegistry(ContainerRegistry):
Logger.log("d", "Converting ContainerStack {stack} to {type}", stack = container.getId(), type = container_type) Logger.log("d", "Converting ContainerStack {stack} to {type}", stack = container.getId(), type = container_type)
new_stack = None
if container_type == "extruder_train": if container_type == "extruder_train":
new_stack = ExtruderStack.ExtruderStack(container.getId()) new_stack = ExtruderStack.ExtruderStack(container.getId())
else: else:
@ -706,7 +705,10 @@ class CuraContainerRegistry(ContainerRegistry):
instance_container = InstanceContainer(container_id) instance_container = InstanceContainer(container_id)
with open(file_path, "r", encoding = "utf-8") as f: with open(file_path, "r", encoding = "utf-8") as f:
serialized = f.read() serialized = f.read()
instance_container.deserialize(serialized, file_path) try:
instance_container.deserialize(serialized, file_path)
except ContainerFormatError:
continue
self.addContainer(instance_container) self.addContainer(instance_container)
break break

View file

@ -12,9 +12,11 @@ import xml.etree.ElementTree as ET
from UM.Workspace.WorkspaceReader import WorkspaceReader from UM.Workspace.WorkspaceReader import WorkspaceReader
from UM.Application import Application from UM.Application import Application
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
from UM.Logger import Logger from UM.Logger import Logger
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from UM.Signal import postponeSignals, CompressTechnique from UM.Signal import postponeSignals, CompressTechnique
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.ContainerStack import ContainerStack from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
@ -332,7 +334,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
containers_found_dict["quality_changes"] = True containers_found_dict["quality_changes"] = True
# Check if there really is a conflict by comparing the values # Check if there really is a conflict by comparing the values
instance_container = InstanceContainer(container_id) instance_container = InstanceContainer(container_id)
instance_container.deserialize(serialized, file_name = instance_container_file_name) try:
instance_container.deserialize(serialized, file_name = instance_container_file_name)
except ContainerFormatError:
continue
if quality_changes[0] != instance_container: if quality_changes[0] != instance_container:
quality_changes_conflict = True quality_changes_conflict = True
elif container_type == "quality": elif container_type == "quality":
@ -639,8 +644,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
definitions = self._container_registry.findDefinitionContainersMetadata(id = container_id) definitions = self._container_registry.findDefinitionContainersMetadata(id = container_id)
if not definitions: if not definitions:
definition_container = DefinitionContainer(container_id) definition_container = DefinitionContainer(container_id)
definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"), try:
file_name = definition_container_file) definition_container.deserialize(archive.open(definition_container_file).read().decode("utf-8"),
file_name = definition_container_file)
except ContainerFormatError:
continue #Skip this definition container file. Pretend there is none.
self._container_registry.addContainer(definition_container) self._container_registry.addContainer(definition_container)
Job.yieldThread() Job.yieldThread()
@ -679,8 +687,11 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
if to_deserialize_material: if to_deserialize_material:
material_container = xml_material_profile(container_id) material_container = xml_material_profile(container_id)
material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"), try:
file_name = container_id + "." + self._material_container_suffix) material_container.deserialize(archive.open(material_container_file).read().decode("utf-8"),
file_name = container_id + "." + self._material_container_suffix)
except ContainerFormatError:
continue #Pretend that this material didn't exist.
if need_new_name: if need_new_name:
new_name = ContainerRegistry.getInstance().uniqueName(material_container.getName()) new_name = ContainerRegistry.getInstance().uniqueName(material_container.getName())
material_container.setName(new_name) material_container.setName(new_name)
@ -704,7 +715,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
# To solve this, we schedule _updateActiveMachine() for later so it will have the latest data. # To solve this, we schedule _updateActiveMachine() for later so it will have the latest data.
self._updateActiveMachine(global_stack) self._updateActiveMachine(global_stack)
# Load all the nodes / meshdata of the workspace # Load all the nodes / mesh data of the workspace
nodes = self._3mf_mesh_reader.read(file_name) nodes = self._3mf_mesh_reader.read(file_name)
if nodes is None: if nodes is None:
nodes = [] nodes = []

View file

@ -1,9 +1,10 @@
# Copyright (c) 2016 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import configparser import configparser
from UM.PluginRegistry import PluginRegistry from UM.PluginRegistry import PluginRegistry
from UM.Logger import Logger from UM.Logger import Logger
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make. from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make.
from cura.ProfileReader import ProfileReader from cura.ProfileReader import ProfileReader
@ -77,7 +78,10 @@ class CuraProfileReader(ProfileReader):
profile.addMetaDataEntry("type", "quality_changes") profile.addMetaDataEntry("type", "quality_changes")
try: try:
profile.deserialize(serialized) profile.deserialize(serialized)
except Exception as e: # Parsing error. This is not a (valid) Cura profile then. except ContainerFormatError as e:
Logger.log("e", "Error in the format of a container: %s", str(e))
return None
except Exception as e:
Logger.log("e", "Error while trying to parse profile: %s", str(e)) Logger.log("e", "Error while trying to parse profile: %s", str(e))
return None return None
return profile return profile

View file

@ -1,9 +1,10 @@
# Copyright (c) 2015 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import re #Regular expressions for parsing escape characters in the settings. import re #Regular expressions for parsing escape characters in the settings.
import json import json
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
from UM.Logger import Logger from UM.Logger import Logger
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
@ -113,6 +114,9 @@ def readQualityProfileFromString(profile_string):
profile = InstanceContainer("") profile = InstanceContainer("")
try: try:
profile.deserialize(profile_string) profile.deserialize(profile_string)
except ContainerFormatError as e:
Logger.log("e", "Corrupt profile in this g-code file: %s", str(e))
return None
except Exception as e: # Not a valid g-code file. except Exception as e: # Not a valid g-code file.
Logger.log("e", "Unable to serialise the profile: %s", str(e)) Logger.log("e", "Unable to serialise the profile: %s", str(e))
return None return None

View file

@ -1,12 +1,12 @@
# Copyright (c) 2015 Jaime van Kessel # Copyright (c) 2015 Jaime van Kessel
# Copyright (c) 2017 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. # The PostProcessingPlugin is released under the terms of the AGPLv3 or higher.
from UM.Logger import Logger
from UM.Signal import Signal, signalemitter from UM.Signal import Signal, signalemitter
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
# Setting stuff import # Setting stuff import
from UM.Application import Application from UM.Application import Application
from UM.Settings.ContainerFormatError import ContainerFormatError
from UM.Settings.ContainerStack import ContainerStack from UM.Settings.ContainerStack import ContainerStack
from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.InstanceContainer import InstanceContainer
from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.DefinitionContainer import DefinitionContainer
@ -39,8 +39,12 @@ class Script:
self._definition = definitions[0] self._definition = definitions[0]
else: else:
self._definition = DefinitionContainer(setting_data["key"]) self._definition = DefinitionContainer(setting_data["key"])
self._definition.deserialize(json.dumps(setting_data)) try:
ContainerRegistry.getInstance().addContainer(self._definition) self._definition.deserialize(json.dumps(setting_data))
ContainerRegistry.getInstance().addContainer(self._definition)
except ContainerFormatError:
self._definition = None
return
self._stack.addContainer(self._definition) self._stack.addContainer(self._definition)
self._instance = InstanceContainer(container_id="ScriptInstanceContainer") self._instance = InstanceContainer(container_id="ScriptInstanceContainer")
self._instance.setDefinition(self._definition.getId()) self._instance.setDefinition(self._definition.getId())