def installPlugin(self, plugin_path: str) -> Optional[Dict[str, str]]: plugin_path = QUrl(plugin_path).toLocalFile() plugin_id = self._getPluginIdFromFile(plugin_path) if plugin_id is None: #Failed to load. return None # Remove it from the to-be-removed list if it's there if plugin_id in self._plugins_to_remove: self._plugins_to_remove.remove(plugin_id) self._savePluginData() # Copy the plugin file to the cache directory so it can later be used for installation cache_dir = os.path.join(Resources.getCacheStoragePath(), "plugins") if not os.path.exists(cache_dir): os.makedirs(cache_dir, exist_ok = True) cache_plugin_filename = os.path.join(cache_dir, plugin_id + ".plugin") if os.path.exists(cache_plugin_filename): os.remove(cache_plugin_filename) shutil.copy2(plugin_path, cache_plugin_filename) # Add new install data install_info = {"plugin_id": plugin_id, "filename": cache_plugin_filename} self._plugins_to_install[plugin_id] = install_info self._savePluginData() Logger.log("i", "Plugin '%s' has been scheduled for installation.", plugin_id) result = {"status": "ok", "id": "", "message": i18n_catalog.i18nc("@info:status", "The plugin has been installed.\nPlease re-start the application to activate the plugin."), } return result
def installPackage(self, filename: str) -> Optional[str]: has_changes = False package_id = "" try: # Get package information package_info = self.getPackageInfo(filename) if not package_info: return None package_id = package_info["package_id"] # If the package is being installed but it is in the list on to remove, then it is deleted from that list. if package_id in self._to_remove_package_set: self._to_remove_package_set.remove(package_id) # We do not check if the same package has been installed already here because, for example, in Cura, # it may need to install a package with the same package-version but with a higher SDK version. So, # the package-version is not the only version that can be in play here. # Need to use the lock file to prevent concurrent I/O issues. with self._container_registry.lockFile(): Logger.log( "i", "Package [%s] version [%s] is scheduled to be installed.", package_id, package_info["package_version"]) # Copy the file to cache dir so we don't need to rely on the original file to be present package_cache_dir = os.path.join( os.path.abspath(Resources.getCacheStoragePath()), "cura_packages") if not os.path.exists(package_cache_dir): os.makedirs(package_cache_dir, exist_ok=True) target_file_path = os.path.join(package_cache_dir, package_id + ".curapackage") shutil.copy2(filename, target_file_path) self._to_install_package_dict[package_id] = { "package_info": package_info, "filename": target_file_path } has_changes = True except: Logger.logException("c", "Failed to install package file '%s'", filename) finally: self._saveManagementData() if has_changes: self.installedPackagesChanged.emit() if package_id in self._packages_with_update_available: # After installing the update, the check will return that not other updates are available. # In that case we remove it from the list. This is actually a safe check (could be removed) if not self.checkIfPackageCanUpdate(package_id): # The install ensured that the package no longer has a valid update option. self._packages_with_update_available.remove(package_id) self.packagesWithUpdateChanged.emit() if has_changes: return package_id else: return None
def installPackage(self, filename: str) -> None: has_changes = False try: # Get package information package_info = self.getPackageInfo(filename) if not package_info: return package_id = package_info["package_id"] # Check the delayed installation and removal lists first if package_id in self._to_remove_package_set: self._to_remove_package_set.remove(package_id) has_changes = True # Check if it is installed installed_package_info = self.getInstalledPackageInfo( package_info["package_id"]) to_install_package = installed_package_info is None # Install if the package has not been installed if installed_package_info is not None: # Compare versions and only schedule the installation if the given package is newer new_version = package_info["package_version"] installed_version = installed_package_info["package_version"] if Version(new_version) > Version(installed_version): Logger.log( "i", "Package [%s] version [%s] is newer than the installed version [%s], update it.", package_id, new_version, installed_version) to_install_package = True if to_install_package: # Need to use the lock file to prevent concurrent I/O issues. with self._container_registry.lockFile(): Logger.log( "i", "Package [%s] version [%s] is scheduled to be installed.", package_id, package_info["package_version"]) # Copy the file to cache dir so we don't need to rely on the original file to be present package_cache_dir = os.path.join( os.path.abspath(Resources.getCacheStoragePath()), "cura_packages") if not os.path.exists(package_cache_dir): os.makedirs(package_cache_dir, exist_ok=True) target_file_path = os.path.join( package_cache_dir, package_id + ".curapackage") shutil.copy2(filename, target_file_path) self._to_install_package_dict[package_id] = { "package_info": package_info, "filename": target_file_path } has_changes = True except: Logger.logException("c", "Failed to install package file '%s'", filename) finally: self._saveManagementData() if has_changes: self.installedPackagesChanged.emit()
def _backupAndStartClean(self): # backup the current cura directories and create clean ones from cura.CuraVersion import CuraVersion from UM.Resources import Resources # The early crash may happen before those information is set in Resources, so we need to set them here to # make sure that Resources can find the correct place. Resources.ApplicationIdentifier = "cura" Resources.ApplicationVersion = CuraVersion config_path = Resources.getConfigStoragePath() data_path = Resources.getDataStoragePath() cache_path = Resources.getCacheStoragePath() folders_to_backup = [] folders_to_remove = [] # only cache folder needs to be removed folders_to_backup.append(config_path) if data_path != config_path: folders_to_backup.append(data_path) # Only remove the cache folder if it's not the same as data or config if cache_path not in (config_path, data_path): folders_to_remove.append(cache_path) for folder in folders_to_remove: shutil.rmtree(folder, ignore_errors=True) for folder in folders_to_backup: base_name = os.path.basename(folder) root_dir = os.path.dirname(folder) import datetime date_now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") idx = 0 file_name = base_name + "_" + date_now zip_file_path = os.path.join(root_dir, file_name + ".zip") while os.path.exists(zip_file_path): idx += 1 file_name = base_name + "_" + date_now + "_" + idx zip_file_path = os.path.join(root_dir, file_name + ".zip") try: # remove the .zip extension because make_archive() adds it zip_file_path = zip_file_path[:-4] shutil.make_archive(zip_file_path, "zip", root_dir=root_dir, base_dir=base_name) # remove the folder only when the backup is successful shutil.rmtree(folder, ignore_errors=True) # create an empty folder so Resources will not try to copy the old ones os.makedirs(folder, 0o0755, exist_ok=True) except Exception as e: Logger.logException("e", "Failed to backup [%s] to file [%s]", folder, zip_file_path) if not self.has_started: print("Failed to backup [%s] to file [%s]: %s", folder, zip_file_path, e) self.early_crash_dialog.close()
def _getDatabaseConnection(self) -> db.Connection: if self._db_connection is not None: return self._db_connection db_path = os.path.join(Resources.getCacheStoragePath(), "containers.db") if not os.path.exists(db_path): self._db_connection = self._createDatabaseFile(db_path) return self._db_connection self._db_connection = db.Connection(db_path) return self._db_connection
def installPackage(self, filename: str) -> None: has_changes = False try: # Get package information package_info = self.getPackageInfo(filename) if not package_info: return package_id = package_info["package_id"] # Check the delayed installation and removal lists first if package_id in self._to_remove_package_set: self._to_remove_package_set.remove(package_id) has_changes = True # Check if it is installed installed_package_info = self.getInstalledPackageInfo(package_info["package_id"]) to_install_package = installed_package_info is None # Install if the package has not been installed if installed_package_info is not None: # Compare versions and only schedule the installation if the given package is newer new_version = package_info["package_version"] installed_version = installed_package_info["package_version"] if Version(new_version) > Version(installed_version): Logger.log("i", "Package [%s] version [%s] is newer than the installed version [%s], update it.", package_id, new_version, installed_version) to_install_package = True if to_install_package: # Need to use the lock file to prevent concurrent I/O issues. with self._container_registry.lockFile(): Logger.log("i", "Package [%s] version [%s] is scheduled to be installed.", package_id, package_info["package_version"]) # Copy the file to cache dir so we don't need to rely on the original file to be present package_cache_dir = os.path.join(os.path.abspath(Resources.getCacheStoragePath()), "cura_packages") if not os.path.exists(package_cache_dir): os.makedirs(package_cache_dir, exist_ok=True) target_file_path = os.path.join(package_cache_dir, package_id + ".curapackage") shutil.copy2(filename, target_file_path) self._to_install_package_dict[package_id] = {"package_info": package_info, "filename": target_file_path} has_changes = True except: Logger.logException("c", "Failed to install package file '%s'", filename) finally: self._saveManagementData() if has_changes: self.installedPackagesChanged.emit()
def installPackage(self, filename: str) -> None: has_changes = False package_id = "" try: # Get package information package_info = self.getPackageInfo(filename) if not package_info: return package_id = package_info["package_id"] # If the package is being installed but it is in the list on to remove, then it is deleted from that list. if package_id in self._to_remove_package_set: self._to_remove_package_set.remove(package_id) # We do not check if the same package has been installed already here because, for example, in Cura, # it may need to install a package with the same package-version but with a higher SDK version. So, # the package-version is not the only version that can be in play here. # Need to use the lock file to prevent concurrent I/O issues. with self._container_registry.lockFile(): Logger.log("i", "Package [%s] version [%s] is scheduled to be installed.", package_id, package_info["package_version"]) # Copy the file to cache dir so we don't need to rely on the original file to be present package_cache_dir = os.path.join(os.path.abspath(Resources.getCacheStoragePath()), "cura_packages") if not os.path.exists(package_cache_dir): os.makedirs(package_cache_dir, exist_ok=True) target_file_path = os.path.join(package_cache_dir, package_id + ".curapackage") shutil.copy2(filename, target_file_path) self._to_install_package_dict[package_id] = {"package_info": package_info, "filename": target_file_path} has_changes = True except: Logger.logException("c", "Failed to install package file '%s'", filename) finally: self._saveManagementData() if has_changes: self.installedPackagesChanged.emit() if package_id in self._packages_with_update_available: if self.checkIfPackageCanUpdate(package_id): # The install ensured that the package no longer has a valid update option. self._packages_with_update_available.remove(package_id) self.packagesWithUpdateChanged.emit()
def _recreateCorruptDataBase(self, cursor: Optional[db.Cursor]) -> None: """Closes the Database, removes the file from cache and recreate all metadata from scratch""" if not cursor: self.loadAllMetadata() return try: cursor.execute("rollback") # Cancel any ongoing transaction. except: # Could be that the cursor is already closed pass cursor.close() self._db_connection = None db_path = os.path.join(Resources.getCacheStoragePath(), "containers.db") try: os.remove(db_path) except EnvironmentError: # Was already deleted by rollback. pass self.loadAllMetadata()
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) # Make sure that a new database connection is used. db_path = os.path.join(Resources.getCacheStoragePath(), "containers.db") if os.path.exists(db_path): os.remove(db_path) container_registry._db_connection = None UM.Settings.ContainerStack.setContainerRegistry(registry) UM.Settings.InstanceContainer.setContainerRegistry(registry) return registry
def installPackage(self, filename: str) -> Optional[str]: """Schedules the given package file to be installed upon the next start. :return: The to-be-installed package_id or None if something went wrong """ has_changes = True package_id = "" try: # Get package information package_info = self.getPackageInfo(filename) if not package_info: return None package_id = package_info["package_id"] # If the package is being installed but it is in the list on to remove, then it is deleted from that list. if package_id in self._to_remove_package_set: self._to_remove_package_set.remove(package_id) # We do not check if the same package has been installed already here because, for example, in Cura, # it may need to install a package with the same package-version but with a higher SDK version. So, # the package-version is not the only version that can be in play here. # Need to use the lock file to prevent concurrent I/O issues. with self._container_registry.lockFile(): Logger.log( "i", "Package [%s] version [%s] is scheduled to be installed.", package_id, package_info["package_version"]) # Copy the file to cache dir so we don't need to rely on the original file to be present package_cache_dir = os.path.join( os.path.abspath(Resources.getCacheStoragePath()), "cura_packages") if not os.path.exists(package_cache_dir): os.makedirs(package_cache_dir, exist_ok=True) target_file_path = os.path.join(package_cache_dir, package_id + ".curapackage") shutil.copy2(filename, target_file_path) self._to_install_package_dict[package_id] = { "package_info": package_info, "filename": target_file_path } except: has_changes = False Logger.logException("c", "Failed to install package file '%s'", filename) finally: self._saveManagementData() if has_changes: self.installedPackagesChanged.emit() if package_id in self._packages_with_update_available: self.packagesWithUpdateChanged.emit() if has_changes: self.packageInstalled.emit(package_id) return package_id else: self.packageInstallingFailed.emit(package_id) return None