def loadFromFile(self, file_path: str) -> None: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path))) if not os.path.isfile(file_path): Logger.log("e", "[%s] is not a file", file_path) return None parser = ConfigParser(interpolation = None, allow_no_value = True) # Accept options without any value, parser.read([file_path]) if not parser.has_option("general", "name") or not parser.has_option("general", "weight"): return None settings = [] # type: List[str] for section in parser.sections(): if section == "general": continue settings.append(section) for option in parser[section].keys(): settings.append(option) self.setSettings(settings) self.setId(item_id) self.setName(parser["general"]["name"]) self.setWeight(int(parser["general"]["weight"]))
def loadFromFile(self, file_path: str) -> None: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) item_id = urllib.parse.unquote_plus( mime_type.stripExtension(os.path.basename(file_path))) if not os.path.isfile(file_path): Logger.log("e", "[%s] is not a file", file_path) return None parser = ConfigParser( interpolation=None, allow_no_value=True) # Accept options without any value, parser.read([file_path]) if not parser.has_option("general", "name") or not parser.has_option( "general", "weight"): return None settings = [] # type: List[str] for section in parser.sections(): if section == "general": continue settings.append(section) for option in parser[section].keys(): settings.append(option) self.setSettings(settings) self.setId(item_id) self.setName(parser["general"]["name"]) self.setWeight(int(parser["general"]["weight"]))
def read(self, file_name: str) -> Union[SceneNode, List[SceneNode]]: """Read mesh data from file and returns a node that contains the data Note that in some cases you can get an entire scene of nodes in this way (eg; 3MF) :return: node :type{SceneNode} or :type{list(SceneNode)} The SceneNode or SceneNodes read from file. """ file_name = resolveAnySymlink(file_name) result = self._read(file_name) UM.Application.Application.getInstance().getController().getScene( ).addWatchedFile(file_name) # The mesh reader may set a MIME type itself if it knows a more specific MIME type than just going by extension. # If not, automatically generate one from our MIME type database, going by the file extension. if not isinstance(result, list): meshes = [result] else: meshes = result for mesh in meshes: if mesh.source_mime_type is None: try: mesh.source_mime_type = MimeTypeDatabase.getMimeTypeForFile( file_name) except MimeTypeNotFoundError: Logger.warning( f"Loaded file {file_name} has no associated MIME type." ) # Leave MIME type at None then. return result
def load(self): files = [] for resource_type in self._resource_types: resources = Resources.getAllResourcesOfType(resource_type) try: resource_storage_path = Resources.getStoragePathForType(resource_type) except UnsupportedStorageTypeError: resource_storage_path = "" # Pre-process the list of files to insert relevant data # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack for path in resources: mime = MimeTypeDatabase.getMimeTypeForFile(path) container_type = self.__mime_type_map.get(mime.name) if not container_type: Logger.log("w", "Could not determine container type for file %s, ignoring", path) continue type_priority = 2 if issubclass(container_type, DefinitionContainer.DefinitionContainer): type_priority = 0 if issubclass(container_type, InstanceContainer.InstanceContainer): type_priority = 1 # Since we have the mime type and resource type here, process these two properties so we do not # need to look up mime types etc. again. container_id = urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path))) read_only = os.path.dirname(path) != resource_storage_path files.append((type_priority, container_id, path, read_only, container_type)) # Sort the list of files by type_priority so we can ensure correct loading order. files = sorted(files, key = lambda i: i[0]) for _, container_id, file_path, read_only, container_type in files: if container_id in self._id_container_cache: continue try: if issubclass(container_type, DefinitionContainer.DefinitionContainer): definition = self._loadCachedDefinition(container_id, file_path) if definition: self.addContainer(definition) continue new_container = container_type(container_id) with open(file_path, encoding = "utf-8") as f: new_container.deserialize(f.read()) new_container.setReadOnly(read_only) if issubclass(container_type, DefinitionContainer.DefinitionContainer): self._saveCachedDefinition(new_container) self.addContainer(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id)
def importMaterialContainer( self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not file_url_or_string: return {"status": "error", "message": "Invalid path"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() else: file_url = file_url_or_string if not file_url or not os.path.exists(file_url): return {"status": "error", "message": "Invalid path"} try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: return { "status": "error", "message": "Could not determine mime type of file" } container_type = self._container_registry.getContainerForMimeType( mime_type) if not container_type: return { "status": "error", "message": "Could not find a container to handle the specified file." } container_id = urllib.parse.unquote_plus( mime_type.stripExtension(os.path.basename(file_url))) container_id = self._container_registry.uniqueName(container_id) container = container_type(container_id) try: with open(file_url, "rt", encoding="utf-8") as f: container.deserialize(f.read()) except PermissionError: return { "status": "error", "message": "Permission denied when trying to read the file" } except Exception as ex: return {"status": "error", "message": str(ex)} container.setDirty(True) self._container_registry.addContainer(container) return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) }
def _pathToMime(self, path: str) -> Optional[MimeType]: try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path)) return None if mime.name not in ContainerRegistry.mime_type_map: # The MIME type is known, but it's not a container. return None return mime
def _pathToMime(self, path) -> Optional[MimeType]: try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path)) return None if mime.name not in ContainerRegistry.mime_type_map: # The MIME type is known, but it's not a container. return None return mime
def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not container_id or not file_type or not file_url_or_string: return {"status": "error", "message": "Invalid arguments"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() else: file_url = file_url_or_string if not file_url: return {"status": "error", "message": "Invalid path"} if file_type not in self._container_name_filters: try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: return {"status": "error", "message": "Unknown File Type"} else: mime_type = self._container_name_filters[file_type]["mime"] containers = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry().findContainers(id = container_id) if not containers: return {"status": "error", "message": "Container not found"} container = containers[0] if Platform.isOSX() and "." in file_url: file_url = file_url[:file_url.rfind(".")] for suffix in mime_type.suffixes: if file_url.endswith(suffix): break else: file_url += "." + mime_type.preferredSuffix if not Platform.isWindows(): if os.path.exists(file_url): result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc("@label Don't translate the XML tag <filename>!", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_url)) if result == QMessageBox.No: return {"status": "cancelled", "message": "User cancelled"} try: contents = container.serialize() except NotImplementedError: return {"status": "error", "message": "Unable to serialize container"} if contents is None: return {"status": "error", "message": "Serialization returned None. Unable to write to file"} try: with SaveFile(file_url, "w") as f: f.write(contents) except OSError: return {"status": "error", "message": "Unable to write to this location.", "path": file_url} return {"status": "success", "message": "Successfully exported container", "path": file_url}
def convertPathToId(path: str) -> str: mime = None try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: pass if mime: return urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path))) else: return ""
def setBaseName(self, base_name: str, is_project_file: bool = False) -> None: self._is_user_specified_job_name = False # Ensure that we don't use entire path but only filename name = os.path.basename(base_name) # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. check_name = os.path.splitext(name)[0] filename_parts = os.path.basename(base_name).split(".") # If it's a gcode, also always update the job name is_gcode = False if len(filename_parts) > 1: # Only check the extension(s) is_gcode = "gcode" in filename_parts[1:] # if this is a profile file, always update the job name # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again is_empty = check_name == "" if is_gcode or is_project_file or ( is_empty or (self._base_name == "" and self._base_name != check_name)): # Only take the file name part, Note : file name might have 'dot' in name as well data = "" try: mime_type = MimeTypeDatabase.getMimeTypeForFile(name) data = mime_type.stripExtension(name) except MimeTypeNotFoundError: Logger.log("w", "Unsupported Mime Type Database file extension %s", name) if data is not None and check_name is not None: self._base_name = data else: self._base_name = "" # Strip the old "curaproject" extension from the name OLD_CURA_PROJECT_EXT = ".curaproject" if self._base_name.lower().endswith(OLD_CURA_PROJECT_EXT): self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_EXT)] # CURA-5896 Try to strip extra extensions with an infinite amount of ".curaproject.3mf". OLD_CURA_PROJECT_3MF_EXT = ".curaproject.3mf" while self._base_name.lower().endswith(OLD_CURA_PROJECT_3MF_EXT): self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_3MF_EXT )] self._updateJobName()
def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not container_id or not file_type or not file_url_or_string: return { "status": "error", "message": "Invalid arguments"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() else: file_url = file_url_or_string if not file_url: return { "status": "error", "message": "Invalid path"} mime_type = None if not file_type in self._container_name_filters: try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: return { "status": "error", "message": "Unknown File Type" } else: mime_type = self._container_name_filters[file_type]["mime"] containers = self._container_registry.findContainers(None, id = container_id) if not containers: return { "status": "error", "message": "Container not found"} container = containers[0] if Platform.isOSX() and "." in file_url: file_url = file_url[:file_url.rfind(".")] for suffix in mime_type.suffixes: if file_url.endswith(suffix): break else: file_url += "." + mime_type.preferredSuffix if not Platform.isWindows(): if os.path.exists(file_url): result = QMessageBox.question(None, catalog.i18nc("@title:window", "File Already Exists"), catalog.i18nc("@label", "The file <filename>{0}</filename> already exists. Are you sure you want to overwrite it?").format(file_url)) if result == QMessageBox.No: return { "status": "cancelled", "message": "User cancelled"} try: contents = container.serialize() except NotImplementedError: return { "status": "error", "message": "Unable to serialize container"} if contents is None: return {"status": "error", "message": "Serialization returned None. Unable to write to file"} with SaveFile(file_url, "w") as f: f.write(contents) return { "status": "success", "message": "Succesfully exported container", "path": file_url}
def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: """Imports a profile from a file :param file_url: A URL that points to the file to import. :return: :type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key containing a message for the user """ if not file_url_or_string: return {"status": "error", "message": "Invalid path"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() else: file_url = file_url_or_string if not file_url or not os.path.exists(file_url): return {"status": "error", "message": "Invalid path"} try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: return {"status": "error", "message": "Could not determine mime type of file"} container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() container_type = container_registry.getContainerForMimeType(mime_type) if not container_type: return {"status": "error", "message": "Could not find a container to handle the specified file."} if not issubclass(container_type, InstanceContainer): return {"status": "error", "message": "This is not a material container, but another type of file."} container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url))) container_id = container_registry.uniqueName(container_id) container = container_type(container_id) try: with open(file_url, "rt", encoding = "utf-8") as f: container.deserialize(f.read(), file_url) except PermissionError: 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: return {"status": "error", "message": str(ex)} container.setDirty(True) container_registry.addContainer(container) return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
def convertPathToId(path: str) -> str: """Try to return Id for given path by looking at its existence in the mimetype database""" mime = None try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: pass if mime: return urllib.parse.unquote_plus( mime.stripExtension(os.path.basename(path))) else: return ""
def _pathToMime(path: str) -> Optional[MimeType]: """Converts a file path to the MIME type of the container it represents. :return: The MIME type or None if it's not a container. """ try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: Logger.log("w", "MIME type could not be found for file: {path}, ignoring it.".format(path = path)) return None if mime.name not in ContainerRegistry.mime_type_map: # The MIME type is known, but it's not a container. return None return mime
def _populate(self): from cura.CuraApplication import CuraApplication items = [] for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset): try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) except MimeTypeNotFoundError: Logger.log("e", "Could not determine mime type of file %s", file_path) continue item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path))) if not os.path.isfile(file_path): Logger.log("e", "[%s] is not a file", file_path) continue parser = ConfigParser(allow_no_value = True) # accept options without any value, try: parser.read([file_path]) if not parser.has_option("general", "name") or not parser.has_option("general", "weight"): continue settings = [] for section in parser.sections(): if section == 'general': continue settings.append(section) for option in parser[section].keys(): settings.append(option) items.append({ "id": item_id, "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]), "weight": parser["general"]["weight"], "settings": settings, }) except Exception: Logger.logException("e", "Failed to load setting preset %s", file_path) items.sort(key = lambda k: (int(k["weight"]), k["id"])) # Put "custom" at the top items.insert(0, {"id": "custom", "name": "Custom selection", "weight": -100, "settings": []}) self.setItems(items)
def _populate(self) -> None: from cura.CuraApplication import CuraApplication items = [] # type: List[Dict[str, Union[str, int, List[str]]]] for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset): try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) except MimeTypeNotFoundError: Logger.log("e", "Could not determine mime type of file %s", file_path) continue item_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_path))) if not os.path.isfile(file_path): Logger.log("e", "[%s] is not a file", file_path) continue parser = ConfigParser(allow_no_value = True) # accept options without any value, try: parser.read([file_path]) if not parser.has_option("general", "name") or not parser.has_option("general", "weight"): continue settings = [] # type: List[str] for section in parser.sections(): if section == 'general': continue settings.append(section) for option in parser[section].keys(): settings.append(option) items.append({ "id": item_id, "name": catalog.i18nc("@action:inmenu", parser["general"]["name"]), "weight": parser["general"]["weight"], "settings": settings, }) except Exception: Logger.logException("e", "Failed to load setting preset %s", file_path) items.sort(key = lambda k: (int(k["weight"]), k["id"])) # type: ignore # Put "custom" at the top items.insert(0, {"id": "custom", "name": "Custom selection", "weight": -100, "settings": []}) self.setItems(items)
def _sendMaterials(self, materials_to_send: Set[str]) -> None: file_paths = Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.MaterialInstanceContainer) # Find all local material files and send them if needed. for file_path in file_paths: try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) except MimeTypeDatabase.MimeTypeNotFoundError: continue file_name = os.path.basename(file_path) material_id = urllib.parse.unquote_plus(mime_type.stripExtension(file_name)) if material_id not in materials_to_send: # If the material does not have to be sent we skip it. continue self._sendMaterialFile(file_path, file_name, material_id)
def setBaseName(self, base_name: str, is_project_file: bool = False) -> None: self._is_user_specified_job_name = False # Ensure that we don't use entire path but only filename name = os.path.basename(base_name) # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. check_name = os.path.splitext(name)[0] filename_parts = os.path.basename(base_name).split(".") # If it's a gcode, also always update the job name is_gcode = False if len(filename_parts) > 1: # Only check the extension(s) is_gcode = "gcode" in filename_parts[1:] # if this is a profile file, always update the job name # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again is_empty = check_name == "" if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != check_name)): # Only take the file name part, Note : file name might have 'dot' in name as well data = "" try: mime_type = MimeTypeDatabase.getMimeTypeForFile(name) data = mime_type.stripExtension(name) except MimeTypeNotFoundError: Logger.log("w", "Unsupported Mime Type Database file extension %s", name) if data is not None and check_name is not None: self._base_name = data else: self._base_name = "" # Strip the old "curaproject" extension from the name OLD_CURA_PROJECT_EXT = ".curaproject" if self._base_name.lower().endswith(OLD_CURA_PROJECT_EXT): self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_EXT)] # CURA-5896 Try to strip extra extensions with an infinite amount of ".curaproject.3mf". OLD_CURA_PROJECT_3MF_EXT = ".curaproject.3mf" while self._base_name.lower().endswith(OLD_CURA_PROJECT_3MF_EXT): self._base_name = self._base_name[:len(self._base_name) - len(OLD_CURA_PROJECT_3MF_EXT)] self._updateJobName()
def _sendMaterials(self, materials_to_send: Set[str]) -> None: file_paths = Resources.getAllResourcesOfType( CuraApplication.ResourceTypes.MaterialInstanceContainer) # Find all local material files and send them if needed. for file_path in file_paths: try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) except MimeTypeDatabase.MimeTypeNotFoundError: continue file_name = os.path.basename(file_path) material_id = urllib.parse.unquote_plus( mime_type.stripExtension(file_name)) if material_id not in materials_to_send: # If the material does not have to be sent we skip it. continue self._sendMaterialFile(file_path, file_name, material_id)
def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: if not file_url_or_string: return {"status": "error", "message": "Invalid path"} if isinstance(file_url_or_string, QUrl): file_url = file_url_or_string.toLocalFile() else: file_url = file_url_or_string if not file_url or not os.path.exists(file_url): return {"status": "error", "message": "Invalid path"} try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_url) except MimeTypeNotFoundError: return {"status": "error", "message": "Could not determine mime type of file"} container_type = self._container_registry.getContainerForMimeType(mime_type) if not container_type: return {"status": "error", "message": "Could not find a container to handle the specified file."} container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url))) container_id = self._container_registry.uniqueName(container_id) container = container_type(container_id) try: with open(file_url, "rt", encoding = "utf-8") as f: container.deserialize(f.read()) except PermissionError: 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: return {"status": "error", "message": str(ex)} container.setDirty(True) self._container_registry.addContainer(container) return {"status": "success", "message": "Successfully imported container {0}".format(container.getName())}
def setBaseName(self, base_name: str, is_project_file: bool = False): self._is_user_specified_job_name = False # Ensure that we don't use entire path but only filename name = os.path.basename(base_name) # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its # extension. This cuts the extension off if necessary. check_name = os.path.splitext(name)[0] filename_parts = os.path.basename(base_name).split(".") # If it's a gcode, also always update the job name is_gcode = False if len(filename_parts) > 1: # Only check the extension(s) is_gcode = "gcode" in filename_parts[1:] # if this is a profile file, always update the job name # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again is_empty = check_name == "" if is_gcode or is_project_file or ( is_empty or (self._base_name == "" and self._base_name != check_name)): # Only take the file name part, Note : file name might have 'dot' in name as well data = '' try: mime_type = MimeTypeDatabase.getMimeTypeForFile(name) data = mime_type.stripExtension(name) except: Logger.log("w", "Unsupported Mime Type Database file extension") if data is not None and check_name is not None: self._base_name = data else: self._base_name = '' self._updateJobName()
def _pathToIdAndMime( path: str) -> Tuple[Optional[str], Optional[MimeType]]: """ Faster combination of _pathToMime and _pathToID When we want to know the mime and the ID, it's better to use this function, as this prevents an extra mime detection from having to be made. """ try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: Logger.log( "w", "MIME type could not be found for file: {path}, ignoring it.". format(path=path)) return None, None if mime.name not in ContainerRegistry.mime_type_map: # The MIME type is known, but it's not a container. return None, None recovered_id = None if mime: recovered_id = urllib.parse.unquote_plus( mime.stripExtension(os.path.basename(path))) return recovered_id, mime
def load(self): files = [] files_resource_type = [] for resource_type in self._resource_types: resources = Resources.getAllResourcesOfType(resource_type) files.extend(resources) files_resource_type.extend([resource_type] * len(resources)) for file_path, resource_type in zip(files, files_resource_type): try: mime = MimeTypeDatabase.getMimeTypeForFile(file_path) container_type = self.__mime_type_map.get(mime.name) container_id = mime.stripExtension(os.path.basename(file_path)) ## Ensure that all special characters are encoded back. container_id = urllib.parse.unquote_plus(container_id) read_only = True try: read_only = os.path.dirname(file_path) != ( Resources.getStoragePathForType(resource_type)) except UnsupportedStorageTypeError: pass if container_type is None: Logger.log("w", "Unable to detect container type for %s", mime.name) continue new_container = container_type(container_id) with open(file_path, encoding="utf-8") as f: new_container.deserialize(f.read()) new_container.setReadOnly(read_only) self._containers.append(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id)
def load(self) -> None: files = [] for resource_type in self._resource_types: resources = Resources.getAllResourcesOfType(resource_type) try: resource_storage_path = Resources.getStoragePathForType( resource_type) except UnsupportedStorageTypeError: resource_storage_path = "" # Pre-process the list of files to insert relevant data # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack for path in resources: try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: # No valid mime type found for file, ignore it. continue container_type = self.__mime_type_map.get(mime.name) if not container_type: Logger.log( "w", "Could not determine container type for file %s, ignoring", path) continue type_priority = container_type.getLoadingPriority() # Since we have the mime type and resource type here, process these two properties so we do not # need to look up mime types etc. again. container_id = urllib.parse.unquote_plus( mime.stripExtension(os.path.basename(path))) read_only = os.path.realpath(os.path.dirname( path)) != os.path.realpath(resource_storage_path) files.append((type_priority, container_id, path, read_only, container_type)) # Sort the list of files by type_priority so we can ensure correct loading order. files = sorted(files, key=lambda i: i[0]) resource_start_time = time.time() for _, container_id, file_path, read_only, container_type in files: if container_id in self._id_container_cache: Logger.log("c", "Found a container with a duplicate ID: %s", container_id) Logger.log( "c", "Existing container is %s, trying to load %s from %s", self._id_container_cache[container_id], container_type, file_path) continue try: if issubclass(container_type, DefinitionContainer): definition = self._loadCachedDefinition( container_id, file_path) if definition: self.addContainer(definition) continue new_container = container_type(container_id) with open(file_path, encoding="utf-8") as f: new_container.deserialize(f.read()) new_container.setReadOnly(read_only) new_container.setPath(file_path) if issubclass(container_type, DefinitionContainer): self._saveCachedDefinition(new_container) self.addContainer(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id) Logger.log("d", "Loading data into container registry took %s seconds", time.time() - resource_start_time)
def getMimeType(self) -> str: """Get the mime type of the selected export file type.""" return MimeTypeDatabase.getMimeTypeForFile(self.getFileName()).name
def _stripFileToId(self, file): mime_type = MimeTypeDatabase.getMimeTypeForFile(file) file = mime_type.stripExtension(file) return file.replace("Cura/", "")
def load(self) -> None: files = [] old_file_expression = re.compile(r"\{sep}old\{sep}\d+\{sep}".format(sep = os.sep)) for resource_type in self._resource_types: resources = Resources.getAllResourcesOfType(resource_type) try: resource_storage_path = Resources.getStoragePathForType(resource_type) except UnsupportedStorageTypeError: resource_storage_path = "" # Pre-process the list of files to insert relevant data # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack for path in resources: if old_file_expression.search(path): # This is a backup file, ignore it. continue try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: # No valid mime type found for file, ignore it. continue container_type = self.__mime_type_map.get(mime.name) if not container_type: Logger.log("w", "Could not determine container type for file %s, ignoring", path) continue type_priority = container_type.getLoadingPriority() # Since we have the mime type and resource type here, process these two properties so we do not # need to look up mime types etc. again. container_id = urllib.parse.unquote_plus(mime.stripExtension(os.path.basename(path))) read_only = os.path.realpath(os.path.dirname(path)) != os.path.realpath(resource_storage_path) files.append((type_priority, container_id, path, read_only, container_type)) # Sort the list of files by type_priority so we can ensure correct loading order. files = sorted(files, key = lambda i: i[0]) resource_start_time = time.time() for _, container_id, file_path, read_only, container_type in files: if container_id in self._id_container_cache: Logger.log("c", "Found a container with a duplicate ID: %s", container_id) Logger.log("c", "Existing container is %s, trying to load %s from %s", self._id_container_cache[container_id], container_type, file_path) continue try: if issubclass(container_type, DefinitionContainer): definition = self._loadCachedDefinition(container_id, file_path) if definition: self.addContainer(definition) continue new_container = container_type(container_id) with open(file_path, encoding = "utf-8") as f: new_container.deserialize(f.read()) new_container.setReadOnly(read_only) new_container.setPath(file_path) if issubclass(container_type, DefinitionContainer): self._saveCachedDefinition(new_container) self.addContainer(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id) Logger.log("d", "Loading data into container registry took %s seconds", time.time() - resource_start_time)
def load(self) -> None: # We disable the garbage collection while loading, as this speeds up the loading. # Since there is so much going on (lots of objects being created), it's better to have it wait a bit until # the dust settles down. gc.disable() files = [] old_file_expression = re.compile( r"\{sep}old\{sep}\d+\{sep}".format(sep=os.sep)) for resource_type in self._resource_types: resources = Resources.getAllResourcesOfType(resource_type) try: resource_storage_path = Resources.getStoragePathForType( resource_type) except UnsupportedStorageTypeError: resource_storage_path = "" # Pre-process the list of files to insert relevant data # Most importantly, we need to ensure the loading order is DefinitionContainer, InstanceContainer, ContainerStack for path in resources: if old_file_expression.search(path): # This is a backup file, ignore it. continue try: mime = MimeTypeDatabase.getMimeTypeForFile(path) except MimeTypeDatabase.MimeTypeNotFoundError: # No valid mime type found for file, ignore it. continue container_type = self.__mime_type_map.get(mime.name) if not container_type: Logger.log( "w", "Could not determine container type for file %s, ignoring", path) continue type_priority = container_type.getLoadingPriority() # Since we have the mime type and resource type here, process these two properties so we do not # need to look up mime types etc. again. container_id = urllib.parse.unquote_plus( mime.stripExtension(os.path.basename(path))) read_only = os.path.realpath(os.path.dirname( path)) != os.path.realpath(resource_storage_path) files.append((type_priority, container_id, path, read_only, container_type)) # Sort the list of files by type_priority so we can ensure correct loading order. files = sorted(files, key=lambda i: i[0]) resource_start_time = time.time() with self.lockCache(): #Because we might be writing cache files. for _, container_id, file_path, read_only, container_type in files: # Enable the rest of the application to get UI updates. UM.Qt.QtApplication.QtApplication.processEvents() if container_id in self._id_container_cache: Logger.log("c", "Found a container with a duplicate ID: %s", container_id) Logger.log( "c", "Existing container is %s, trying to load %s from %s", self._id_container_cache[container_id], container_type, file_path) continue try: if issubclass(container_type, DefinitionContainer): definition = self._loadCachedDefinition( container_id, file_path) if definition: self.addContainer(definition) continue new_container = container_type(container_id) with open(file_path, encoding="utf-8") as f: new_container.deserialize(f.read()) new_container.setReadOnly(read_only) new_container.setPath(file_path) if issubclass(container_type, DefinitionContainer): self._saveCachedDefinition(new_container) self.addContainer(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id) Logger.log("d", "Loading data into container registry took %s seconds", time.time() - resource_start_time) gc.enable()
def sendMissingMaterials(self, reply: QNetworkReply) -> None: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute ) != 200: #Got an error from the HTTP request. Logger.log( "e", "Couldn't request current material storage on printer. Not syncing materials." ) return remote_materials_list = reply.readAll().data().decode("utf-8") try: remote_materials_list = json.loads(remote_materials_list) except json.JSONDecodeError: Logger.log( "e", "Current material storage on printer was a corrupted reply.") return try: remote_materials_by_guid = { material["guid"]: material for material in remote_materials_list } #Index by GUID. except KeyError: Logger.log( "e", "Current material storage on printer was an invalid reply (missing GUIDs)." ) return container_registry = ContainerRegistry.getInstance() local_materials_list = filter( lambda material: ("GUID" in material and "version" in material and "id" in material), container_registry.findContainersMetadata(type="material")) local_materials_by_guid = { material["GUID"]: material for material in local_materials_list if material["id"] == material["base_file"] } for material in local_materials_list: #For each GUID get the material with the highest version number. try: if int(material["version"]) > local_materials_by_guid[ material["GUID"]]["version"]: local_materials_by_guid[material["GUID"]] = material except ValueError: Logger.log( "e", "Material {material_id} has invalid version number {number}." .format(material_id=material["id"], number=material["version"])) continue materials_to_send = set() #type: Set[Dict[str, Any]] for guid, material in local_materials_by_guid.items(): if guid not in remote_materials_by_guid: materials_to_send.add(material["id"]) continue try: if int(material["version"] ) > remote_materials_by_guid[guid]["version"]: materials_to_send.add(material["id"]) continue except KeyError: Logger.log( "e", "Current material storage on printer was an invalid reply (missing version)." ) return for file_path in Resources.getAllResourcesOfType( CuraApplication.ResourceTypes.MaterialInstanceContainer): try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) except MimeTypeDatabase.MimeTypeNotFoundError: continue #Not the sort of file we'd like to send then. _, file_name = os.path.split(file_path) material_id = urllib.parse.unquote_plus( mime_type.stripExtension(file_name)) if material_id not in materials_to_send: continue parts = [] with open(file_path, "rb") as f: parts.append( self.device._createFormPart( "name=\"file\"; filename=\"{file_name}\"".format( file_name=file_name), f.read())) signature_file_path = file_path + ".sig" if os.path.exists(signature_file_path): _, signature_file_name = os.path.split(signature_file_path) with open(signature_file_path, "rb") as f: parts.append( self.device._createFormPart( "name=\"signature_file\"; filename=\"{file_name}\"" .format(file_name=signature_file_name), f.read())) Logger.log( "d", "Syncing material {material_id} with cluster.".format( material_id=material_id)) self.device.postFormWithParts(target="materials/", parts=parts, on_finished=self.sendingFinished)