def setUp(self): self._application = MagicMock() self._container_registry = MagicMock() self._machine_manager = MagicMock() self._mocked_mime = MagicMock() self._mocked_mime.preferredSuffix = "omg" self._mocked_mime.suffixes = ["omg"] self._mocked_mime.comment = "UnitTest!" self._mocked_container = MagicMock() self._mocked_container_data = "SOME DATA :D" self._mocked_container.serialize = MagicMock(return_value = self._mocked_container_data) self._containers_meta_data = [{"id": "test", "test_data": "omg"}] self._container_registry.findContainersMetadata = MagicMock(return_value = self._containers_meta_data) self._container_registry.getMimeTypeForContainer = MagicMock(return_value = self._mocked_mime) self._container_registry.findContainers = MagicMock(return_value = [self._mocked_container]) self._application.getContainerRegistry = MagicMock(return_value = self._container_registry) self._application.getMachineManager = MagicMock(return_value = self._machine_manager) # Destroy the previous instance of the container manager if ContainerManager.getInstance() is not None: ContainerManager._ContainerManager__instance = None self._container_manager = ContainerManager(self._application) MimeTypeDatabase.addMimeType(self._mocked_mime)
def register(app): mime_type = MimeType( name = "application/x-ultimaker-material-profile", comment = "Ultimaker Material Profile", suffixes = [ "xml.fdm_material" ] ) MimeTypeDatabase.addMimeType(mime_type) return { "settings_container": XmlMaterialProfile.XmlMaterialProfile("default_xml_material_profile") }
def __init__(self) -> None: super().__init__() MimeTypeDatabase.addMimeType( MimeType( name = "application/x-cura-compressed-gcode-file", comment = "Cura Compressed GCode File", suffixes = ["gcode.gz"] ) ) self._supported_extensions = [".gcode.gz"]
def __init__(self) -> None: super().__init__() MimeTypeDatabase.addMimeType( MimeType( name = "model/stl", comment = "Uranium STL File", suffixes = ["stl"] ) ) self._supported_extensions = [".stl"]
def __init__(self) -> None: super().__init__() MimeTypeDatabase.addMimeType( MimeType( name = "application/x-ufp", comment = "Ultimaker Format Package", suffixes = ["ufp"] ) ) self._supported_extensions = [".ufp"]
def __init__(self) -> None: super().__init__() self._supported_extensions = [".amf"] self._namespaces = {} # type: Dict[str, str] MimeTypeDatabase.addMimeType( MimeType( name="application/x-amf", comment="AMF", suffixes=["amf"] ) )
def __init__(self): super().__init__(add_to_recent_files = False) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-ufp", comment = "Ultimaker Format Package", suffixes = ["ufp"] ) ) self._snapshot = None
def mime_database(): MimeTypeDatabase._MimeTypeDatabase__custom_mimetypes = [] mime = MimeType( name = "application/x-test", comment = "Test Mimetype", suffixes = [ "test" ] ) MimeTypeDatabase.addMimeType(mime) mime = MimeType( name = "application/x-long-test", comment = "Long Test Mimetype", suffixes = [ "long.test" ] ) MimeTypeDatabase.addMimeType(mime) mime = MimeType( name = "application/x-multiple-test", comment = "Multiple Extension MIME Type", suffixes = [ "tost", "ost" ], preferred_suffix = "ost" ) MimeTypeDatabase.addMimeType(mime) mime = MimeType( name = "image/jpeg", comment = "Custom JPEG MIME Type", suffixes = [ "jpg", "jpeg" ], preferred_suffix = "jpg" ) MimeTypeDatabase.addMimeType(mime) return MimeTypeDatabase
def __init__(self) -> None: super().__init__() MimeTypeDatabase.addMimeType( MimeType( name = "application/x-cura-gcode-file", comment = "Cura GCode File", suffixes = ["gcode"] ) ) self._supported_extensions = [".gcode", ".g"] self._flavor_reader = None Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
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 __init__(self) -> None: super().__init__() MimeTypeDatabase.addMimeType( MimeType( name = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml", comment="3MF", suffixes=["3mf"] ) ) self._supported_extensions = [".3mf"] self._root = None self._base_name = "" self._unit = None self._object_count = 0 # Used to name objects as there is no node name yet.
def setup_module(): MimeTypeDatabase.addMimeType( MimeType( name = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml", comment = "3MF", suffixes = ["3mf"] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-cura-gcode-file", comment = "Cura GCode File", suffixes = ["gcode"] ) )
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 getMimeTypeForContainer(cls, container_type: type) -> Optional[MimeType]: try: mime_type_name = UM.Dictionary.findKey(cls.mime_type_map, container_type) if mime_type_name: return MimeTypeDatabase.getMimeType(mime_type_name) except ValueError: Logger.log("w", "Unable to find mimetype for container %s", container_type) return None
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 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 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 register(app): # add Mime type mime_type = MimeType( name = "application/x-ultimaker-material-profile", comment = "Ultimaker Material Profile", suffixes = [ "xml.fdm_material" ] ) MimeTypeDatabase.addMimeType(mime_type) # add upgrade version from cura.CuraApplication import CuraApplication from UM.VersionUpgradeManager import VersionUpgradeManager VersionUpgradeManager.getInstance().registerCurrentVersion( ("materials", XmlMaterialProfile.XmlMaterialProfile.Version * 1000000 + CuraApplication.SettingVersion), (CuraApplication.ResourceTypes.MaterialInstanceContainer, "application/x-ultimaker-material-profile") ) return {"version_upgrade": upgrader, "settings_container": XmlMaterialProfile.XmlMaterialProfile("default_xml_material_profile"), }
def container_registry(application): MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-definitioncontainer", comment = "Uranium Definition Container", suffixes = ["def.json"] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-instancecontainer", comment = "Uranium Instance Container", suffixes = [ "inst.cfg" ] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-containerstack", comment = "Uranium Container Stack", suffixes = [ "stack.cfg" ] ) ) Resources.addSearchPath(os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..", "Settings"))) ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time PluginRegistry.getInstance().removeType("settings_container") ContainerRegistry.getInstance().load() return ContainerRegistry.getInstance()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) mime = MimeType( name = "application/x-uranium-definitioncontainer", comment = "Uranium Definition Container", suffixes = [ "def.json" ] ) MimeTypeDatabase.addMimeType(mime) mime = MimeType( name = "application/x-uranium-instancecontainer", comment = "Uranium Instance Container", suffixes = [ "inst.cfg" ] ) MimeTypeDatabase.addMimeType(mime) mime = MimeType( name = "application/x-uranium-containerstack", comment = "Uranium Container Stack", suffixes = [ "stack.cfg" ] ) MimeTypeDatabase.addMimeType(mime) self._emptyInstanceContainer = _EmptyInstanceContainer("empty") self._containers = [ self._emptyInstanceContainer ] self._id_container_cache = {} self._resource_types = [Resources.DefinitionContainers]
def container_registry(application): MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-definitioncontainer", comment = "Uranium Definition Container", suffixes = ["def.json"] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-instancecontainer", comment = "Uranium Instance Container", suffixes = [ "inst.cfg" ] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-containerstack", comment = "Uranium Container Stack", suffixes = [ "stack.cfg" ] ) ) Resources.addSearchPath(os.path.dirname(os.path.abspath(__file__))) ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time ContainerRegistry.setApplication(application) UM.Settings.ContainerStack.setContainerRegistry(ContainerRegistry.getInstance()) UM.Settings.InstanceContainer.setContainerRegistry(ContainerRegistry.getInstance()) return ContainerRegistry.getInstance()
def container_registry(application, test_containers_provider, plugin_registry: PluginRegistry): MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-definitioncontainer", comment = "Uranium Definition Container", suffixes = ["def.json"] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-instancecontainer", comment = "Uranium Instance Container", suffixes = [ "inst.cfg" ] ) ) MimeTypeDatabase.addMimeType( MimeType( name = "application/x-uranium-containerstack", comment = "Uranium Container Stack", suffixes = [ "stack.cfg" ] ) ) ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time registry = ContainerRegistry(application) #We need to mock the "priority" plug-in metadata field, but preferably without mocking an entire plug-in. with unittest.mock.patch("UM.PluginRegistry.PluginRegistry.getMetaData", unittest.mock.MagicMock(return_value = {"container_provider": {}})): registry.addProvider(test_containers_provider) UM.Settings.ContainerStack.setContainerRegistry(registry) UM.Settings.InstanceContainer.setContainerRegistry(registry) return registry
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 _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 _deleteFiles(self, container): for resource_type in self._resource_types: mime_type_name = "" for name, container_type in self.__mime_type_map.items(): if container_type == container.__class__: mime_type_name = name break else: return mime_type = MimeTypeDatabase.getMimeType(mime_type_name) for suffix in mime_type.suffixes: try: path = Resources.getStoragePath(resource_type, urllib.parse.quote_plus(container.getId()) + "." + suffix) if os.path.isfile(path): os.remove(path) except Exception: continue
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 _getXmlProfileClass(self): return self._container_registry.getContainerForMimeType(MimeTypeDatabase.getMimeType("application/x-ultimaker-material-profile"))
def __init__(self) -> None: super().__init__() self._supported_extensions = [ ".ctm", ".dae", ".gltf", ".glb", ".ply", ".zae" ] MimeTypeDatabase.addMimeType( MimeType(name="application/x-ctm", comment="Open Compressed Triangle Mesh", suffixes=["ctm"])) MimeTypeDatabase.addMimeType( MimeType(name="model/vnd.collada+xml", comment="COLLADA Digital Asset Exchange", suffixes=["dae"])) MimeTypeDatabase.addMimeType( MimeType(name="model/gltf-binary", comment="glTF Binary", suffixes=["glb"])) MimeTypeDatabase.addMimeType( MimeType(name="model/gltf+json", comment="glTF Embedded JSON", suffixes=["gltf"])) # Trimesh seems to have a bug when reading .off files. #MimeTypeDatabase.addMimeType( # MimeType( # name = "application/x-off", # comment = "Geomview Object File Format", # suffixes = ["off"] # ) #) MimeTypeDatabase.addMimeType( MimeType( name= "application/x-ply", # Wikipedia lists the MIME type as "text/plain" but that won't do as it's not unique to PLY files. comment="Stanford Triangle Format", suffixes=["ply"])) MimeTypeDatabase.addMimeType( MimeType(name="model/vnd.collada+xml+zip", comment="Compressed COLLADA Digital Asset Exchange", suffixes=["zae"]))
super().deserialize(contents, file_name) if "enabled" not in self.getMetaData(): self.setMetaDataEntry("enabled", "True") def _onPropertiesChanged(self, key: str, properties: Dict[str, Any]) -> None: # When there is a setting that is not settable per extruder that depends on a value from a setting that is, # we do not always get properly informed that we should re-evaluate the setting. So make sure to indicate # something changed for those settings. if not self.getNextStack(): return #There are no global settings to depend on. definitions = self.getNextStack().definition.findDefinitions(key = key) if definitions: has_global_dependencies = False for relation in definitions[0].relations: if not getattr(relation.target, "settable_per_extruder", True): has_global_dependencies = True break if has_global_dependencies: self.getNextStack().propertiesChanged.emit(key, properties) extruder_stack_mime = MimeType( name = "application/x-cura-extruderstack", comment = "Cura Extruder Stack", suffixes = ["extruder.cfg"] ) MimeTypeDatabase.addMimeType(extruder_stack_mime) ContainerRegistry.addContainerTypeByName(ExtruderStack, "extruder_stack", extruder_stack_mime.name)
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 Logger.info(f"Importing material from {file_url}") 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 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)
class InvalidDefinitionError(Exception): pass class IncorrectDefinitionVersionError(Exception): pass class InvalidOverrideError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-definitioncontainer", comment="Uranium Definition Container", suffixes=["def.json"])) ## A container for SettingDefinition objects. # # class DefinitionContainer(QObject, DefinitionContainerInterface, PluginObject): Version = 2 ## Constructor # # \param container_id A unique, machine readable/writable ID for this container. def __init__(self, container_id: str, i18n_catalog=None, *args, **kwargs): # Note that we explicitly pass None as QObject parent here. This is to be able # to support pickling.
def getMimeTypeForContainer(cls, container_type): mime_type_name = UM.Dictionary.findKey(cls.__mime_type_map, container_type) if mime_type_name: return MimeTypeDatabase.getMimeType(mime_type_name) return None
def _getXmlProfileClass(self): return self._container_registry.getContainerForMimeType( MimeTypeDatabase.getMimeType( "application/x-ultimaker-material-profile"))
def _stripFileToId(self, file): mime_type = MimeTypeDatabase.getMimeTypeForFile(file) file = mime_type.stripExtension(file) return file.replace("Cura/", "")
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 _populate(self) -> None: 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 tearDown(self): MimeTypeDatabase.removeMimeType(self._mocked_mime)
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: 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.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.DefinitionContainer): self._saveCachedDefinition(new_container) self.addContainer(new_container) except Exception as e: Logger.logException("e", "Could not deserialize container %s", container_id)
stacks = ContainerRegistry.getInstance().findContainerStacks(id=self.getMetaDataEntry("machine", "")) if stacks: self.setNextStack(stacks[0]) def _onPropertiesChanged(self, key, properties): # When there is a setting that is not settable per extruder that depends on a value from a setting that is, # we do not always get properly informed that we should re-evaluate the setting. So make sure to indicate # something changed for those settings. if not self.getNextStack(): return #There are no global settings to depend on. definitions = self.getNextStack().definition.findDefinitions(key = key) if definitions: has_global_dependencies = False for relation in definitions[0].relations: if not getattr(relation.target, "settable_per_extruder", True): has_global_dependencies = True break if has_global_dependencies: self.getNextStack().propertiesChanged.emit(key, properties) extruder_stack_mime = MimeType( name = "application/x-cura-extruderstack", comment = "Cura Extruder Stack", suffixes = ["extruder.cfg"] ) MimeTypeDatabase.addMimeType(extruder_stack_mime) ContainerRegistry.addContainerTypeByName(ExtruderStack, "extruder_stack", extruder_stack_mime.name)
# Copyright (c) 2013 David Braam # Uranium is released under the terms of the LGPLv3 or higher. from UM.Mesh.MeshReader import MeshReader from UM.Mesh.MeshBuilder import MeshBuilder from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode from UM.Job import Job from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType import os import struct import numpy MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-stl-file", comment="Uranium STL File", suffixes=["stl"])) use_numpystl = False try: import stl # numpy-stl lib import stl.mesh # Increase max count. (10 million should be okay-ish) stl.stl.MAX_COUNT = 10000000 use_numpystl = True except ImportError: Logger.log("w", "Could not find numpy-stl, falling back to slower code.") # We have our own fallback code.
# requested property. def _shouldResolve(self, key: str, property_name: str) -> bool: if property_name is not "value": # Do not try to resolve anything but the "value" property return False if key in self._resolving_settings: # To prevent infinite recursion, if getProperty is called with the same key as # we are already trying to resolve, we should not try to resolve again. Since # this can happen multiple times when trying to resolve a value, we need to # track all settings that are being resolved. return False setting_state = super().getProperty(key, "state") if setting_state is not None and setting_state != InstanceState.Default: # When the user has explicitly set a value, we should ignore any resolve and # just return that value. return False return True ## private: global_stack_mime = MimeType(name="application/x-cura-globalstack", comment="Cura Global Stack", suffixes=["global.cfg"]) MimeTypeDatabase.addMimeType(global_stack_mime) ContainerRegistry.addContainerTypeByName(GlobalStack, "global_stack", global_stack_mime.name)
from UM.Logger import Logger try: from . import UFPWriter except ImportError: Logger.log("w", "Could not import UFPWriter; libCharon may be missing") from UM.i18n import i18nCatalog #To translate the file format description. from UM.Mesh.MeshWriter import MeshWriter #For the binary mode flag. from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType MimeTypeDatabase.addMimeType( MimeType( name = "application/x-cura-stl-file", comment = "Cura UFP File", suffixes = ["ufp"] ) ) i18n_catalog = i18nCatalog("cura") def getMetaData(): if "UFPWriter.UFPWriter" not in sys.modules: return {} return { "mesh_writer": { "output": [ { "mime_type": "application/x-ufp",
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()
import UM.Settings.ContainerRegistry from . import ContainerInterface from . import SettingFunction class IncorrectVersionError(Exception): pass class InvalidContainerStackError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-containerstack", comment="Uranium Container Stack", suffixes=["stack.cfg"])) ## A stack of setting containers to handle setting value retrieval. @signalemitter class ContainerStack(ContainerInterface.ContainerInterface, PluginObject): Version = 2 ## Constructor # # \param stack_id \type{string} A unique, machine readable/writable ID. def __init__(self, stack_id, *args, **kwargs): super().__init__(*args, **kwargs) self._id = str(stack_id)
def exportContainer( self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]: """Export a container to a file :param container_id: The ID of the container to export :param file_type: The type of file to save as. Should be in the form of "description (*.extension, *.ext)" :param file_url_or_string: The URL where to save the file. :return: A dictionary containing a key "status" with a status code and a key "message" with a message explaining the status. The status code can be one of "error", "cancelled", "success" """ 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 } Logger.info( "Successfully exported container to {path}".format(path=file_url)) return { "status": "success", "message": "Successfully exported container", "path": file_url }
from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.GroupDecorator import GroupDecorator from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType from cura.Settings.ExtruderManager import ExtruderManager from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Scene.BuildPlateDecorator import BuildPlateDecorator from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator from cura.Scene.ZOffsetDecorator import ZOffsetDecorator from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch MYPY = False MimeTypeDatabase.addMimeType( MimeType(name="application/x-cura-project-file", comment="Cura Project File", suffixes=["curaproject.3mf"])) try: if not MYPY: import xml.etree.cElementTree as ET except ImportError: Logger.log("w", "Unable to load cElementTree, switching to slower version") import xml.etree.ElementTree as ET ## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes! class ThreeMFReader(MeshReader): def __init__(self): super().__init__() self._supported_extensions = [".3mf"]
def _shouldResolve(self, key: str, property_name: str) -> bool: if property_name is not "value": # Do not try to resolve anything but the "value" property return False if key in self._resolving_settings: # To prevent infinite recursion, if getProperty is called with the same key as # we are already trying to resolve, we should not try to resolve again. Since # this can happen multiple times when trying to resolve a value, we need to # track all settings that are being resolved. return False setting_state = super().getProperty(key, "state") if setting_state is not None and setting_state != InstanceState.Default: # When the user has explicitly set a value, we should ignore any resolve and # just return that value. return False return True ## private: global_stack_mime = MimeType( name = "application/x-cura-globalstack", comment = "Cura Global Stack", suffixes = ["global.cfg"] ) MimeTypeDatabase.addMimeType(global_stack_mime) ContainerRegistry.addContainerTypeByName(GlobalStack, "global_stack", global_stack_mime.name)
class InvalidInstanceError(Exception): pass class IncorrectInstanceVersionError(Exception): pass class DefinitionNotFoundError(Exception): pass MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-instancecontainer", comment="Uranium Instance Container", suffixes=["inst.cfg"])) ## A container for SettingInstance objects. # # @signalemitter class InstanceContainer(ContainerInterface, PluginObject): Version = 2 ## Constructor # # \param container_id A unique, machine readable/writable ID for this container. def __init__(self, container_id, *args, **kwargs): super().__init__(*args, **kwargs)
def getMimeType(self) -> str: """Get the mime type of the selected export file type.""" return MimeTypeDatabase.getMimeTypeForFile(self.getFileName()).name
# Copyright (c) 2018 Ultimaker B.V. # Uranium is released under the terms of the LGPLv3 or higher. import configparser from typing import Any, Dict, IO, Optional, Tuple, Union from UM.Decorators import deprecated from UM.Logger import Logger from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType #To register the MIME type of the preference file. from UM.SaveFile import SaveFile from UM.Signal import Signal, signalemitter MimeTypeDatabase.addMimeType( MimeType(name="application/x-uranium-preferences", comment="Uranium Preferences File", suffixes=["cfg"], preferred_suffix="cfg")) ## Preferences are application based settings that are saved for future use. # Typical preferences would be window size, standard machine, etc. # The application preferences can be gotten from the getPreferences() function in Application @signalemitter class Preferences: Version = 6 def __init__(self) -> None: super().__init__() self._parser = None # type: Optional[configparser.ConfigParser] self._preferences = {} # type: Dict[str, Dict[str, _Preference]]
# Copyright (c) 2017 Aleph Objects, Inc. # Cura is released under the terms of the LGPLv3 or higher. from UM.FileHandler.FileReader import FileReader from UM.Mesh.MeshReader import MeshReader from UM.i18n import i18nCatalog from UM.Application import Application from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType catalog = i18nCatalog("cura") from . import MarlinFlavorParser, RepRapFlavorParser MimeTypeDatabase.addMimeType( MimeType(name="application/x-cura-gcode-file", comment="Cura GCode File", suffixes=["gcode", "gcode.gz"])) # Class for loading and parsing G-code files class GCodeReader(MeshReader): _flavor_default = "Marlin" _flavor_keyword = ";FLAVOR:" _flavor_readers_dict = { "RepRap": RepRapFlavorParser.RepRapFlavorParser(), "Marlin": MarlinFlavorParser.MarlinFlavorParser() } def __init__(self) -> None: super().__init__() self._supported_extensions = [".gcode", ".g"] self._flavor_reader = None
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 }