Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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()
Esempio n. 5
0
    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()
Esempio n. 6
0
 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
Esempio n. 7
0
    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()
Esempio n. 8
0
    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()
Esempio n. 9
0
    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()
Esempio n. 10
0
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
Esempio n. 11
0
    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