diff options
author | Lipu Fei <lipu.fei815@gmail.com> | 2017-07-06 11:22:31 +0300 |
---|---|---|
committer | Lipu Fei <lipu.fei815@gmail.com> | 2017-07-06 11:26:02 +0300 |
commit | 42858b47152060557d9258744ff1538e2dd64697 (patch) | |
tree | 1c352e88e4372d7ec99f01219486c990ca2e32ba /plugins/VersionUpgrade/VersionUpgrade26to27 | |
parent | 16a078b9a66b7cf77b1bfd5c2a134f0be058f15e (diff) |
Add upgrade script for 2.6 to 2.7 to rename quality profiles
CURA-3975
Diffstat (limited to 'plugins/VersionUpgrade/VersionUpgrade26to27')
4 files changed, 350 insertions, 0 deletions
diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py b/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py new file mode 100644 index 0000000000..c0e085bcfb --- /dev/null +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/VersionUpgrade26to27.py @@ -0,0 +1,120 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import configparser #To parse the files we need to upgrade and write the new files. +import io #To serialise configparser output to a string. + +from UM.VersionUpgrade import VersionUpgrade +from cura.CuraApplication import CuraApplication + +# a dict of renamed quality profiles: <old_id> : <new_id> +_renamed_quality_profiles = { + "um3_aa0.4_PVA_Not_Supported_Quality": "um3_aa0.4_PVA_Fast_Print", + + "um3_aa0.8_CPEP_Not_Supported_Quality": "um3_aa0.8_CPEP_Fast_Print", + "um3_aa0.8_CPEP_Not_Supported_Superdraft_Quality": "um3_aa0.8_CPEP_Superdraft_Print", + "um3_aa0.8_CPEP_Not_Supported_Verydraft_Quality": "um3_aa0.8_CPEP_Verydraft_Print", + + "um3_aa0.8_PC_Not_Supported_Quality": "um3_aa0.8_PC_Fast_Print", + "um3_aa0.8_PC_Not_Supported_Superdraft_Quality": "um3_aa0.8_PC_Superdraft_Print", + "um3_aa0.8_PC_Not_Supported_Verydraft_Quality": "um3_aa0.8_PC_Verydraft_Print", + + "um3_aa0.8_PVA_Not_Supported_Quality": "um3_aa0.8_PVA_Fast_Print", + "um3_aa0.8_PVA_Not_Supported_Superdraft_Quality": "um3_aa0.8_PVA_Superdraft_Print", + + "um3_bb0.4_ABS_Not_Supported_Quality": "um3_bb0.4_ABS_Fast_print", + "um3_bb0.4_ABS_Not_Supported_Superdraft_Quality": "um3_bb0.4_ABS_Superdraft_Print", + + "um3_bb0.4_CPE_Not_Supported_Quality": "um3_bb0.4_CPE_Fast_Print", + "um3_bb0.4_CPE_Not_Supported_Superdraft_Quality": "um3_bb0.4_CPE_Superdraft_Print", + + "um3_bb0.4_CPEP_Not_Supported_Quality": "um3_bb0.4_CPEP_Fast_Print", + "um3_bb0.4_CPEP_Not_Supported_Superdraft_Quality": "um3_bb0.4_CPEP_Superdraft_Print", + + "um3_bb0.4_Nylon_Not_Supported_Quality": "um3_bb0.4_Nylon_Fast_Print", + "um3_bb0.4_Nylon_Not_Supported_Superdraft_Quality": "um3_bb0.4_Nylon_Superdraft_Print", + + "um3_bb0.4_PC_Not_Supported_Quality": "um3_bb0.4_PC_Fast_Print", + + "um3_bb0.4_PLA_Not_Supported_Quality": "um3_bb0.4_PLA_Fast_Print", + "um3_bb0.4_PLA_Not_Supported_Superdraft_Quality": "um3_bb0.4_PLA_Superdraft_Print", + + "um3_bb0.4_TPU_Not_Supported_Quality": "um3_bb0.4_TPU_Fast_Print", + "um3_bb0.4_TPU_Not_Supported_Superdraft_Quality": "um3_bb0.4_TPU_Superdraft_Print", + + "um3_bb0.8_ABS_Not_Supported_Quality": "um3_bb0.8_ABS_Fast_Print", + "um3_bb0.8_ABS_Not_Supported_Superdraft_Quality": "um3_bb0.8_ABS_Superdraft_Print", + + "um3_bb0.8_CPE_Not_Supported_Quality": "um3_bb0.8_CPE_Fast_Print", + "um3_bb0.8_CPE_Not_Supported_Superdraft_Quality": "um3_bb0.8_CPE_Superdraft_Print", + + "um3_bb0.8_CPEP_Not_Supported_Quality": "um3_bb0.um3_bb0.8_CPEP_Fast_Print", + "um3_bb0.8_CPEP_Not_Supported_Superdraft_Quality": "um3_bb0.8_CPEP_Superdraft_Print", + + "um3_bb0.8_Nylon_Not_Supported_Quality": "um3_bb0.8_Nylon_Fast_Print", + "um3_bb0.8_Nylon_Not_Supported_Superdraft_Quality": "um3_bb0.8_Nylon_Superdraft_Print", + + "um3_bb0.8_PC_Not_Supported_Quality": "um3_bb0.8_PC_Fast_Print", + "um3_bb0.8_PC_Not_Supported_Superdraft_Quality": "um3_bb0.8_PC_Superdraft_Print", + + "um3_bb0.8_PLA_Not_Supported_Quality": "um3_bb0.8_PLA_Fast_Print", + "um3_bb0.8_PLA_Not_Supported_Superdraft_Quality": "um3_bb0.8_PLA_Superdraft_Print", + + "um3_bb0.8_TPU_Not_Supported_Quality": "um3_bb0.8_TPU_Fast_print", + "um3_bb0.8_TPU_Not_Supported_Superdraft_Quality": "um3_bb0.8_TPU_Superdraft_Print", +} + +## A collection of functions that convert the configuration of the user in Cura +# 2.6 to a configuration for Cura 2.7. +# +# All of these methods are essentially stateless. +class VersionUpgrade26to27(VersionUpgrade): + ## Gets the version number from a CFG file in Uranium's 2.6 format. + # + # Since the format may change, this is implemented for the 2.6 format only + # and needs to be included in the version upgrade system rather than + # globally in Uranium. + # + # \param serialised The serialised form of a CFG file. + # \return The version number stored in the CFG file. + # \raises ValueError The format of the version number in the file is + # incorrect. + # \raises KeyError The format of the file is incorrect. + def getCfgVersion(self, serialised): + parser = configparser.ConfigParser(interpolation = None) + parser.read_string(serialised) + format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised. + setting_version = int(parser.get("metadata", "setting_version", fallback = 0)) + return format_version * 1000000 + setting_version + + ## Upgrades a container stack from version 2.6 to 2.7. + # + # \param serialised The serialised form of a container stack. + # \param filename The name of the file to upgrade. + def upgradeStack(self, serialised, filename): + parser = configparser.ConfigParser(interpolation = None) + parser.read_string(serialised) + + # Update IDs of the renamed quality profiles + if parser.has_section("containers"): + key_list = [key for key in parser["containers"].keys()] + for key in key_list: + container_id = parser.get("containers", key) + new_id = _renamed_quality_profiles.get(container_id) + if new_id is not None: + parser.set("containers", key, new_id) + + for each_section in ("general", "metadata"): + if not parser.has_section(each_section): + parser.add_section(each_section) + + # Change the version number in the file. + parser["metadata"]["setting_version"] = str(CuraApplication.SettingVersion) + + # Update version + parser["general"]["version"] = "4" + + # Re-serialise the file. + output = io.StringIO() + parser.write(output) + return [filename], [output.getvalue()] diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py b/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py new file mode 100644 index 0000000000..8ddf4aa7ea --- /dev/null +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/__init__.py @@ -0,0 +1,31 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from . import VersionUpgrade26to27 + +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +upgrade = VersionUpgrade26to27.VersionUpgrade26to27() + +def getMetaData(): + return { + "version_upgrade": { + # From To Upgrade function + ("machine_stack", 3000000): ("machine_stack", 3000002, upgrade.upgradeStack), + ("extruder_train", 3000000): ("extruder_train", 3000002, upgrade.upgradeStack), + }, + "sources": { + "machine_stack": { + "get_version": upgrade.getCfgVersion, + "location": {"./machine_instances"} + }, + "extruder_train": { + "get_version": upgrade.getCfgVersion, + "location": {"./extruders"} + }, + } + } + +def register(app): + return { "version_upgrade": upgrade } diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json new file mode 100644 index 0000000000..3c3d7fff8c --- /dev/null +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json @@ -0,0 +1,8 @@ + { + "name": "Version Upgrade 2.6 to 2.7", + "author": "Ultimaker B.V.", + "version": "1.0.0", + "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", + "api": 4, + "i18n-catalog": "cura" +} diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py b/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py new file mode 100644 index 0000000000..f8e3561b38 --- /dev/null +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/tests/TestVersionUpgrade26to27.py @@ -0,0 +1,191 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import configparser #To check whether the appropriate exceptions are raised. +import pytest #To register tests with. + +import VersionUpgrade26to27 #The module we're testing. + +## Creates an instance of the upgrader to test with. +@pytest.fixture +def upgrader(): + return VersionUpgrade26to27.VersionUpgrade26to27() + +test_cfg_version_good_data = [ + { + "test_name": "Simple", + "file_data": """[general] +version = 1 +""", + "version": 1000000 + }, + { + "test_name": "Other Data Around", + "file_data": """[nonsense] +life = good + +[general] +version = 3 + +[values] +layer_height = 0.12 +infill_sparse_density = 42 +""", + "version": 3000000 + }, + { + "test_name": "Negative Version", #Why not? + "file_data": """[general] +version = -20 +""", + "version": -20000000 + }, + { + "test_name": "Setting Version", + "file_data": """[general] +version = 1 +[metadata] +setting_version = 1 +""", + "version": 1000001 + }, + { + "test_name": "Negative Setting Version", + "file_data": """[general] +version = 1 +[metadata] +setting_version = -3 +""", + "version": 999997 + } +] + +## Tests the technique that gets the version number from CFG files. +# +# \param data The parametrised data to test with. It contains a test name +# to debug with, the serialised contents of a CFG file and the correct +# version number in that CFG file. +# \param upgrader The instance of the upgrade class to test. +@pytest.mark.parametrize("data", test_cfg_version_good_data) +def test_cfgVersionGood(data, upgrader): + version = upgrader.getCfgVersion(data["file_data"]) + assert version == data["version"] + +test_cfg_version_bad_data = [ + { + "test_name": "Empty", + "file_data": "", + "exception": configparser.Error #Explicitly not specified further which specific error we're getting, because that depends on the implementation of configparser. + }, + { + "test_name": "No General", + "file_data": """[values] +layer_height = 0.1337 +""", + "exception": configparser.Error + }, + { + "test_name": "No Version", + "file_data": """[general] +true = false +""", + "exception": configparser.Error + }, + { + "test_name": "Not a Number", + "file_data": """[general] +version = not-a-text-version-number +""", + "exception": ValueError + }, + { + "test_name": "Setting Value NaN", + "file_data": """[general] +version = 4 +[metadata] +setting_version = latest_or_something +""", + "exception": ValueError + }, + { + "test_name": "Major-Minor", + "file_data": """[general] +version = 1.2 +""", + "exception": ValueError + } +] + +## Tests whether getting a version number from bad CFG files gives an +# exception. +# +# \param data The parametrised data to test with. It contains a test name +# to debug with, the serialised contents of a CFG file and the class of +# exception it needs to throw. +# \param upgrader The instance of the upgrader to test. +@pytest.mark.parametrize("data", test_cfg_version_bad_data) +def test_cfgVersionBad(data, upgrader): + with pytest.raises(data["exception"]): + upgrader.getCfgVersion(data["file_data"]) + +test_upgrade_stacks_with_not_supported_data = [ + { + "test_name": "Global stack with Not Supported quality profile", + "file_data": """[general] +version = 3 +name = Ultimaker 3 +id = Ultimaker 3 + +[metadata] +type = machine + +[containers] +0 = Ultimaker 3_user +1 = empty +2 = um3_global_Normal_Quality +3 = empty +4 = empty +5 = empty +6 = ultimaker3 +""" + }, + { + "test_name": "Extruder stack left with Not Supported quality profile", + "file_data": """[general] +version = 3 +name = Extruder 1 +id = ultimaker3_extruder_left #2 + +[metadata] +position = 0 +machine = Ultimaker 3 +type = extruder_train + +[containers] +0 = ultimaker3_extruder_left #2_user +1 = empty +2 = um3_aa0.4_PVA_Not_Supported_Quality +3 = generic_pva_ultimaker3_AA_0.4 +4 = ultimaker3_aa04 +5 = ultimaker3_extruder_left #2_settings +6 = ultimaker3_extruder_left +""" + } +] + +## Tests whether the "Not Supported" quality profiles in the global and extruder stacks are renamed for the 2.7 +# version of preferences. +@pytest.mark.parametrize("data", test_upgrade_stacks_with_not_supported_data) +def test_upgradeStacksWithNotSupportedQuality(data, upgrader): + # Read old file + original_parser = configparser.ConfigParser(interpolation = None) + original_parser.read_string(data["file_data"]) + + # Perform the upgrade. + _, upgraded_stacks = upgrader.upgradeStack(data["file_data"], "<string>") + upgraded_stack = upgraded_stacks[0] + + # Find whether the not supported profile has been renamed + parser = configparser.ConfigParser(interpolation = None) + parser.read_string(upgraded_stack) + assert("Not_Supported" not in parser.get("containers", "2")) |