mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-23 14:44:13 -06:00
use bytes to pass backup file around, generate in memory, small fixes
This commit is contained in:
parent
64819d517e
commit
936de402ec
3 changed files with 17 additions and 20 deletions
|
@ -1,7 +1,5 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from zipfile import ZipFile
|
|
||||||
|
|
||||||
from cura.Backups.BackupsManager import BackupsManager
|
from cura.Backups.BackupsManager import BackupsManager
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,14 +16,14 @@ class Backups:
|
||||||
|
|
||||||
manager = BackupsManager() # Re-used instance of the backups manager.
|
manager = BackupsManager() # Re-used instance of the backups manager.
|
||||||
|
|
||||||
def createBackup(self) -> ("ZipFile", dict):
|
def createBackup(self) -> (bytes, dict):
|
||||||
"""
|
"""
|
||||||
Create a new backup using the BackupsManager.
|
Create a new backup using the BackupsManager.
|
||||||
:return: Tuple containing a ZIP file with the backup data and a dict with meta data about the backup.
|
:return: Tuple containing a ZIP file with the backup data and a dict with meta data about the backup.
|
||||||
"""
|
"""
|
||||||
return self.manager.createBackup()
|
return self.manager.createBackup()
|
||||||
|
|
||||||
def restoreBackup(self, zip_file: "ZipFile", meta_data: dict) -> None:
|
def restoreBackup(self, zip_file: bytes, meta_data: dict) -> None:
|
||||||
"""
|
"""
|
||||||
Restore a backup using the BackupManager.
|
Restore a backup using the BackupManager.
|
||||||
:param zip_file: A ZIP file containing the actual backup data.
|
:param zip_file: A ZIP file containing the actual backup data.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile
|
from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ class Backup:
|
||||||
It is also responsible for reading and writing the zip file to the user data folder.
|
It is also responsible for reading and writing the zip file to the user data folder.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, zip_file: "ZipFile" = None, meta_data: dict = None):
|
def __init__(self, zip_file: bytes = None, meta_data: dict = None):
|
||||||
self.zip_file = zip_file # type: Optional[ZipFile]
|
self.zip_file = zip_file # type: Optional[bytes]
|
||||||
self.meta_data = meta_data # type: Optional[dict
|
self.meta_data = meta_data # type: Optional[dict]
|
||||||
|
|
||||||
def makeFromCurrent(self) -> (bool, Optional[str]):
|
def makeFromCurrent(self) -> (bool, Optional[str]):
|
||||||
"""
|
"""
|
||||||
|
@ -26,13 +26,12 @@ class Backup:
|
||||||
"""
|
"""
|
||||||
cura_release = CuraApplication.getInstance().getVersion()
|
cura_release = CuraApplication.getInstance().getVersion()
|
||||||
version_data_dir = Resources.getDataStoragePath()
|
version_data_dir = Resources.getDataStoragePath()
|
||||||
timestamp = datetime.now().isoformat()
|
|
||||||
|
|
||||||
Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir)
|
Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir)
|
||||||
|
|
||||||
# We're using an easy to parse filename for when we're restoring edge cases:
|
# We're using an easy to parse filename for when we're restoring edge cases:
|
||||||
# TIMESTAMP.backup.VERSION.cura.zip
|
# TIMESTAMP.backup.VERSION.cura.zip
|
||||||
archive = self._makeArchive("{}.backup.{}.cura.zip".format(timestamp, cura_release), version_data_dir)
|
archive = self._makeArchive(version_data_dir)
|
||||||
|
|
||||||
self.zip_file = archive
|
self.zip_file = archive
|
||||||
self.meta_data = {
|
self.meta_data = {
|
||||||
|
@ -41,30 +40,30 @@ class Backup:
|
||||||
# TODO: fill meta data with machine/material/etc counts.
|
# TODO: fill meta data with machine/material/etc counts.
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _makeArchive(root_path: str, archive_name: str) -> Optional[ZipFile]:
|
def _makeArchive(root_path: str) -> Optional[bytes]:
|
||||||
"""
|
"""
|
||||||
Make a full archive from the given root path with the given name.
|
Make a full archive from the given root path with the given name.
|
||||||
:param root_path: The root directory to archive recursively.
|
:param root_path: The root directory to archive recursively.
|
||||||
:param archive_name: The name of the archive to create.
|
:return: The archive as bytes.
|
||||||
:return: The archive as ZipFile.
|
|
||||||
"""
|
"""
|
||||||
parent_folder = os.path.dirname(root_path)
|
parent_folder = os.path.dirname(root_path)
|
||||||
contents = os.walk(root_path)
|
contents = os.walk(root_path)
|
||||||
try:
|
try:
|
||||||
archive = ZipFile(archive_name, "w", ZIP_DEFLATED)
|
buffer = io.BytesIO()
|
||||||
|
archive = ZipFile(buffer, "w", ZIP_DEFLATED)
|
||||||
for root, folders, files in contents:
|
for root, folders, files in contents:
|
||||||
for folder_name in folders:
|
for folder_name in folders:
|
||||||
# Add all folders, even empty ones.
|
# Add all folders, even empty ones.
|
||||||
absolute_path = os.path.join(root, folder_name)
|
absolute_path = os.path.join(root, folder_name)
|
||||||
relative_path = absolute_path.replace(parent_folder + '\\', '')
|
relative_path = absolute_path.replace(parent_folder + '\\', '')
|
||||||
archive.write(absolute_path, relative_path)
|
archive.write(relative_path)
|
||||||
for file_name in files:
|
for file_name in files:
|
||||||
# Add all files.
|
# Add all files.
|
||||||
absolute_path = os.path.join(root, file_name)
|
absolute_path = os.path.join(root, file_name)
|
||||||
relative_path = absolute_path.replace(parent_folder + '\\', '')
|
relative_path = absolute_path.replace(parent_folder + '\\', '')
|
||||||
archive.write(absolute_path, relative_path)
|
archive.write(relative_path)
|
||||||
archive.close()
|
archive.close()
|
||||||
return archive
|
return buffer.getvalue()
|
||||||
except (IOError, OSError, BadZipfile) as error:
|
except (IOError, OSError, BadZipfile) as error:
|
||||||
Logger.log("e", "Could not create archive from user data directory: %s", error)
|
Logger.log("e", "Could not create archive from user data directory: %s", error)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from zipfile import ZipFile
|
from typing import Optional
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from cura.Backups.Backup import Backup
|
from cura.Backups.Backup import Backup
|
||||||
|
@ -12,7 +12,7 @@ class BackupsManager:
|
||||||
Backups themselves are represented in a different class.
|
Backups themselves are represented in a different class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def createBackup(self) -> ("ZipFile", dict):
|
def createBackup(self) -> (Optional[bytes], Optional[dict]):
|
||||||
"""
|
"""
|
||||||
Get a backup of the current configuration.
|
Get a backup of the current configuration.
|
||||||
:return: A Tuple containing a ZipFile (the actual backup) and a dict containing some meta data (like version).
|
:return: A Tuple containing a ZipFile (the actual backup) and a dict containing some meta data (like version).
|
||||||
|
@ -24,7 +24,7 @@ class BackupsManager:
|
||||||
# We don't return a Backup here because we want plugins only to interact with our API and not full objects.
|
# We don't return a Backup here because we want plugins only to interact with our API and not full objects.
|
||||||
return backup.zip_file, backup.meta_data
|
return backup.zip_file, backup.meta_data
|
||||||
|
|
||||||
def restoreBackup(self, zip_file: "ZipFile", meta_data: dict) -> None:
|
def restoreBackup(self, zip_file: bytes, meta_data: dict) -> None:
|
||||||
"""
|
"""
|
||||||
Restore a backup from a given ZipFile.
|
Restore a backup from a given ZipFile.
|
||||||
:param zip_file: A ZipFile containing the actual backup.
|
:param zip_file: A ZipFile containing the actual backup.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue