From 9671ae3c741432ef144499f0b3179ac4447269b2 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 11 Dec 2015 17:27:18 +0100 Subject: [PATCH 01/17] Introduce blanco LegacySettings plugin This plugin will be implemented to import settings from legacy versions of Cura. Contributes to issue CURA-37. --- plugins/LegacySettings/LegacySettings.py | 8 ++++++++ plugins/LegacySettings/__init__.py | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 plugins/LegacySettings/LegacySettings.py create mode 100644 plugins/LegacySettings/__init__.py diff --git a/plugins/LegacySettings/LegacySettings.py b/plugins/LegacySettings/LegacySettings.py new file mode 100644 index 0000000000..e2f6be50af --- /dev/null +++ b/plugins/LegacySettings/LegacySettings.py @@ -0,0 +1,8 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from UM.Extension import Extension + +class LegacySettings(Extension): + def __init__(self): + super().__init__() \ No newline at end of file diff --git a/plugins/LegacySettings/__init__.py b/plugins/LegacySettings/__init__.py new file mode 100644 index 0000000000..ee2eb46e77 --- /dev/null +++ b/plugins/LegacySettings/__init__.py @@ -0,0 +1,21 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from . import LegacySettings + +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +def getMetaData(): + return { + "plugin": { + "name": catalog.i18nc("@label", "GCode Reader"), + "author": "Ultimaker", + "version": "1.0", + "description": catalog.i18nc("@info:whatsthis", "Provides support for reading GCode files."), + "api": 2 + } + } + +def register(app): + return { "extension": LegacySettings.LegacySettings() } From 513941097f8d84365c94ea3d0f6905cd7026bea9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 17 Dec 2015 13:20:25 +0100 Subject: [PATCH 02/17] Initial LegacyProfileReader plugin implementation This plugin reads a profile from legacy Cura versions. It hasn't been tested much except that there are no syntax errors. It is currently being blocked by issue 34. Contributes to issue CURA-37. --- .../LegacyProfileReader/DictionaryOfDoom.json | 75 +++++++++++++++++ .../LegacyProfileReader.py | 84 +++++++++++++++++++ plugins/LegacyProfileReader/__init__.py | 27 ++++++ 3 files changed, 186 insertions(+) create mode 100644 plugins/LegacyProfileReader/DictionaryOfDoom.json create mode 100644 plugins/LegacyProfileReader/LegacyProfileReader.py create mode 100644 plugins/LegacyProfileReader/__init__.py diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json new file mode 100644 index 0000000000..c357c72bcd --- /dev/null +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -0,0 +1,75 @@ +{ + "source_version": "15.04", + "target_version": "2.1", + + "translation": { + "line_width": "nozzle_size", + "layer_height": "layer_height", + "layer_height_0": "bottom_thickness", + "shell_thickness": "wall_thickness", + "top_bottom_thickness": "solid_layer_thickness", + "top_thickness": "solid_top", + "bottom_thickness": "solid_bottom", + "skin_no_small_gaps_heuristic": "fix_horrible_extensive_stitching", + "infill_sparse_density": "fill_density", + "infill_overlap": "fill_overlap", + "infill_before_walls": "perimeter_before_infill", + "material_print_temperature": "print_temperature", + "material_bed_temperature": "print_bed_temperature", + "material_diameter": "filament_diameter", + "material_flow": "filament_flow", + "retraction_enable": "retraction_enable", + "retraction_amount": "retraction_amount", + "retraction_speed": "retraction_speed", + "retraction_min_travel": "retraction_min_travel", + "retraction_hop": "retraction_hop", + "speed_print": "print_speed", + "speed_infill": "infill_speed", + "speed_wall_0": "inset0_speed", + "speed_wall_x": "insetx_speed", + "speed_topbottom": "solidarea_speed", + "speed_travel": "travel_speed", + "speed_layer_0": "bottom_layer_speed", + "retraction_combing": "retraction_combing", + "cool_fan_enabled": "fan_enabled", + "cool_fan_speed_min": "fan_speed", + "cool_fan_speed_max": "fan_speed_max", + "cool_fan_full_at_height": "fan_full_height", + "cool_min_layer_time": "cool_min_layer_time", + "cool_min_speed": "cool_min_feedrate", + "cool_lift_head": "cool_head_lift", + "support_enable": "support == \"None\" ? False : True", + "support_type": "support == \"Touching buildplate\" ? \"buildplate\" : \"everywhere\"", + "support_angle": "support_angle", + "support_xy_distance": "support_xy_distance", + "support_z_distance": "support_z_distance", + "support_pattern": "support_type.lower()", + "support_infill_rate": "support_fill_rate", + "platform_adhesion": "platform_adhesion.lower()", + "skirt_line_count": "skirt_line_count", + "skirt_gap": "skirt_gap", + "skirt_minimal_length": "skirt_minimal_length", + "brim_line_count": "brim_line_count", + "raft_margin": "raft_margin", + "raft_airgap": "raft_airgap_all", + "raft_surface_layers": "raft_surface_layers", + "raft_surface_thickness": "raft_surface_thickness", + "raft_surface_line_width": "raft_surface_linewidth", + "raft_surface_line_spacing": "raft_line_spacing", + "raft_interface_thickness": "raft_interface_thickness", + "raft_interface_line_width": "raft_interface_linewidth", + "raft_interface_line_spacing": "raft_line_spacing", + "raft_base_thickness": "raft_base_thickness", + "raft_base_line_width": "raft_base_linewidth", + "raft_base_line_spacing": "raft_line_spacing", + "meshfix_union_all": "fix_horrible_union_all_type_a", + "meshfix_union_all_remove_holes": "fix_horrible_union_all_type_b", + "meshfix_extensive_stitching": "fix_horrible_extensive_stitching", + "meshfix_keep_open_polygons": "fix_horrible_use_open_bits", + "magic_mesh_surface_mode": "simple_mode", + "magic_spiralize": "spiralize", + "prime_tower_enable": "wipe_tower", + "prime_tower_size": "sqrt(wipe_tower_volume / layer_height)", + "ooze_shield_enabled": "ooze_shield" + } +} \ No newline at end of file diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py new file mode 100644 index 0000000000..1ff8ef330a --- /dev/null +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -0,0 +1,84 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +import json #For reading the Dictionary of Doom. + +from UM.Application import Application #To get the machine manager to create the new profile in. +from UM.Settings.Profile import Profile +from UM.Settings.ProfileReader import ProfileReader + +## A plugin that reads profile data from legacy Cura versions. +# +# It reads a profile from an .ini file, and performs some translations on it. +# Not all translations are correct, mind you, but it is a best effort. +class LegacyProfileReader(ProfileReader): + ## Initialises the legacy profile reader. + # + # This does nothing since the only other function is basically stateless. + def __init__(self): + super().__init__() + + ## Reads a legacy Cura profile from a file and returns it. + # + # \param file_name The file to read the legacy Cura profile from. + # \return The legacy Cura profile that was in the file, if any. If the + # file could not be read or didn't contain a valid profile, \code None + # \endcode is returned. + def read(self, file_name): + profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile. + profile.setName("Imported Legacy Profile") + + stream = io.StringIO(serialised) #ConfigParser needs to read from a stream. + parser = configparser.ConfigParser(interpolation = None) + parser.readfp(stream) + + #Legacy Cura saved the profile under the section "profile_N" where N is the ID of a machine, except when you export in which case it saves it in the section "profile". + #Since importing multiple machine profiles is out of scope, just import the first section we find. + section = "" + for found_section in parser.sections(): + if found_section.startsWith("profile"): + section = found_section + break + if not section: #No section starting with "profile" was found. Probably not a proper INI file. + return None + + legacy_settings = prepareLocals(parser, section) #Gets the settings from the legacy profile. + + try: + with open(os.path.join(PluginRegistry.getInstance().getPluginPath("LegacyProfileReader"), "DictionaryOfDoom.json"), "r", -1, "utf-8") as f: + dict_of_doom = json.load(f) #Parse the Dictionary of Doom. + except IOError as e: + Logger.log("e", "Could not open DictionaryOfDoom.json for reading: %s", str(e)) + return None + except Exception as e: + Logger.log("e", "Could not parse DictionaryOfDoom.json: %s", str(e)) + return None + + if "translations" not in dict_of_doom: + Logger.log("e", "Dictionary of Doom has no translations. Is it the correct JSON file?") + return None + for new_setting, old_setting_expression in dict_of_doom["translations"]: #Evaluate all new settings that would get a value from the translations. + compiled = compile(old_setting_expression, new_setting, "eval") + new_value = eval(compiled, {}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. + profile.setSettingValue(new_setting, new_value) #Store the setting in the profile! + + return profile + + ## Prepares the local variables that can be used in evaluation of computing + # new setting values from the old ones. + # + # This fills a dictionary with all settings from the legacy Cura version + # and their values, so that they can be used in evaluating the new setting + # values as Python code. + # + # \param parser The ConfigParser that finds the settings in the legacy + # profile. + # \param section The section in the profile where the settings should be + # found. + # \return A set of local variables, one for each setting in the legacy + # profile. + def prepareLocals(self, parser, section): + locals = {} + for option in parser.options(): + locals[option] = parser.get(section, option) + return locals \ No newline at end of file diff --git a/plugins/LegacyProfileReader/__init__.py b/plugins/LegacyProfileReader/__init__.py new file mode 100644 index 0000000000..e3b0ccc4b2 --- /dev/null +++ b/plugins/LegacyProfileReader/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from . import LegacyProfileReader + +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + +def getMetaData(): + return { + "plugin": { + "name": catalog.i18nc("@label", "Legacy Cura Profile Reader"), + "author": "Ultimaker", + "version": "1.0", + "description": catalog.i18nc("@info:whatsthis", "Provides support for importing profiles from legacy Cura versions."), + "api": 2 + }, + "profile_reader": [ + { + "extension": "ini", + "description": catalog.i18nc("@item:inlistbox", "Cura 15.04 profiles") + } + ] + } + +def register(app): + return { "profile_reader": CuraProfileReader.CuraProfileReader() } From 77453cf80f93d5033a306b0afd41ed098fc163d4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 17 Dec 2015 14:01:42 +0100 Subject: [PATCH 03/17] Remove old version of LegacyProfileReader This shouldn't have been committed. I suspect this came in via checking out a branch where this was still on the working tree and then going to a branch where it wasn't, and it kept the files and I thought LegacySettings was the plugin I had to commit. Contributes to issue CURA-37. --- plugins/LegacySettings/LegacySettings.py | 8 -------- plugins/LegacySettings/__init__.py | 21 --------------------- 2 files changed, 29 deletions(-) delete mode 100644 plugins/LegacySettings/LegacySettings.py delete mode 100644 plugins/LegacySettings/__init__.py diff --git a/plugins/LegacySettings/LegacySettings.py b/plugins/LegacySettings/LegacySettings.py deleted file mode 100644 index e2f6be50af..0000000000 --- a/plugins/LegacySettings/LegacySettings.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - -from UM.Extension import Extension - -class LegacySettings(Extension): - def __init__(self): - super().__init__() \ No newline at end of file diff --git a/plugins/LegacySettings/__init__.py b/plugins/LegacySettings/__init__.py deleted file mode 100644 index ee2eb46e77..0000000000 --- a/plugins/LegacySettings/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the AGPLv3 or higher. - -from . import LegacySettings - -from UM.i18n import i18nCatalog -catalog = i18nCatalog("cura") - -def getMetaData(): - return { - "plugin": { - "name": catalog.i18nc("@label", "GCode Reader"), - "author": "Ultimaker", - "version": "1.0", - "description": catalog.i18nc("@info:whatsthis", "Provides support for reading GCode files."), - "api": 2 - } - } - -def register(app): - return { "extension": LegacySettings.LegacySettings() } From 57f5e60fa53af6e183f5dcc880756c057967c9b9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 17 Dec 2015 14:02:29 +0100 Subject: [PATCH 04/17] Fix link to LegacyProfileReader This was preventing the entire plugin from being loaded. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/__init__.py b/plugins/LegacyProfileReader/__init__.py index e3b0ccc4b2..e671f02571 100644 --- a/plugins/LegacyProfileReader/__init__.py +++ b/plugins/LegacyProfileReader/__init__.py @@ -24,4 +24,4 @@ def getMetaData(): } def register(app): - return { "profile_reader": CuraProfileReader.CuraProfileReader() } + return { "profile_reader": LegacyProfileReader.LegacyProfileReader() } From f2a95ae89c63dee80b39e9f68a2121f5985be1b7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 17 Dec 2015 14:30:53 +0100 Subject: [PATCH 05/17] Correct the configparser The import was missing. Also, the parser was not called on the correct stream. Contributes to issue CURA-37. --- .../LegacyProfileReader/LegacyProfileReader.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 1ff8ef330a..2a3df82114 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -1,6 +1,7 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +import configparser #For reading the legacy profile INI files. import json #For reading the Dictionary of Doom. from UM.Application import Application #To get the machine manager to create the new profile in. @@ -27,10 +28,14 @@ class LegacyProfileReader(ProfileReader): def read(self, file_name): profile = Profile(machine_manager = Application.getInstance().getMachineManager(), read_only = False) #Create an empty profile. profile.setName("Imported Legacy Profile") - - stream = io.StringIO(serialised) #ConfigParser needs to read from a stream. + parser = configparser.ConfigParser(interpolation = None) - parser.readfp(stream) + try: + with open(file_name) as f: + parser.readfp(f) #Parse the INI file. + except Exception as e: + Logger.log("e", "Unable to open legacy profile %s: %s", file_name, str(e)) + return None #Legacy Cura saved the profile under the section "profile_N" where N is the ID of a machine, except when you export in which case it saves it in the section "profile". #Since importing multiple machine profiles is out of scope, just import the first section we find. @@ -41,9 +46,9 @@ class LegacyProfileReader(ProfileReader): break if not section: #No section starting with "profile" was found. Probably not a proper INI file. return None - + legacy_settings = prepareLocals(parser, section) #Gets the settings from the legacy profile. - + try: with open(os.path.join(PluginRegistry.getInstance().getPluginPath("LegacyProfileReader"), "DictionaryOfDoom.json"), "r", -1, "utf-8") as f: dict_of_doom = json.load(f) #Parse the Dictionary of Doom. @@ -53,7 +58,7 @@ class LegacyProfileReader(ProfileReader): except Exception as e: Logger.log("e", "Could not parse DictionaryOfDoom.json: %s", str(e)) return None - + if "translations" not in dict_of_doom: Logger.log("e", "Dictionary of Doom has no translations. Is it the correct JSON file?") return None From abb92afc27497c67943a477b8be93d3b3fa6e437 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 17 Dec 2015 14:54:48 +0100 Subject: [PATCH 06/17] Fix call to prepareLocals Turns out the 'self.' is required... Contributes to issue CURA-37. --- .../LegacyProfileReader.py | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 2a3df82114..26ade400b5 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -19,6 +19,25 @@ class LegacyProfileReader(ProfileReader): def __init__(self): super().__init__() + ## Prepares the local variables that can be used in evaluation of computing + # new setting values from the old ones. + # + # This fills a dictionary with all settings from the legacy Cura version + # and their values, so that they can be used in evaluating the new setting + # values as Python code. + # + # \param parser The ConfigParser that finds the settings in the legacy + # profile. + # \param section The section in the profile where the settings should be + # found. + # \return A set of local variables, one for each setting in the legacy + # profile. + def prepareLocals(self, parser, section): + locals = {} + for option in parser.options(): + locals[option] = parser.get(section, option) + return locals + ## Reads a legacy Cura profile from a file and returns it. # # \param file_name The file to read the legacy Cura profile from. @@ -41,13 +60,13 @@ class LegacyProfileReader(ProfileReader): #Since importing multiple machine profiles is out of scope, just import the first section we find. section = "" for found_section in parser.sections(): - if found_section.startsWith("profile"): + if found_section.startswith("profile"): section = found_section break if not section: #No section starting with "profile" was found. Probably not a proper INI file. return None - legacy_settings = prepareLocals(parser, section) #Gets the settings from the legacy profile. + legacy_settings = self.prepareLocals(parser, section) #Gets the settings from the legacy profile. try: with open(os.path.join(PluginRegistry.getInstance().getPluginPath("LegacyProfileReader"), "DictionaryOfDoom.json"), "r", -1, "utf-8") as f: @@ -67,23 +86,4 @@ class LegacyProfileReader(ProfileReader): new_value = eval(compiled, {}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. profile.setSettingValue(new_setting, new_value) #Store the setting in the profile! - return profile - - ## Prepares the local variables that can be used in evaluation of computing - # new setting values from the old ones. - # - # This fills a dictionary with all settings from the legacy Cura version - # and their values, so that they can be used in evaluating the new setting - # values as Python code. - # - # \param parser The ConfigParser that finds the settings in the legacy - # profile. - # \param section The section in the profile where the settings should be - # found. - # \return A set of local variables, one for each setting in the legacy - # profile. - def prepareLocals(self, parser, section): - locals = {} - for option in parser.options(): - locals[option] = parser.get(section, option) - return locals \ No newline at end of file + return profile \ No newline at end of file From 166c8a304853e02d2e268db933981e65b74d7f0f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:01:22 +0100 Subject: [PATCH 07/17] Fix call to configparser.options It needs to have the section from which to read the options. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/LegacyProfileReader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 26ade400b5..0c714690a5 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -34,7 +34,7 @@ class LegacyProfileReader(ProfileReader): # profile. def prepareLocals(self, parser, section): locals = {} - for option in parser.options(): + for option in parser.options(section): locals[option] = parser.get(section, option) return locals From 644038af97315822fadb2340c5a4d96d6f908b2e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:06:43 +0100 Subject: [PATCH 08/17] Missing imports Test before commit. Test before commit. Test before commit. Test before commit! Contributes to issue CURA-37. --- plugins/LegacyProfileReader/LegacyProfileReader.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 0c714690a5..1afdb25346 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -3,8 +3,11 @@ import configparser #For reading the legacy profile INI files. import json #For reading the Dictionary of Doom. +import os.path #For concatenating the path to the plugin and the relative path to the Dictionary of Doom. from UM.Application import Application #To get the machine manager to create the new profile in. +from UM.Logger import Logger #Logging errors. +from UM.PluginRegistry import PluginRegistry #For getting the path to this plugin's directory. from UM.Settings.Profile import Profile from UM.Settings.ProfileReader import ProfileReader From 6bde0e3404cc226a8e1189efefac1fffd96e0c1e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:10:52 +0100 Subject: [PATCH 09/17] Sync translation category name from JSON The category was named 'translation' instead of 'translations'. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/LegacyProfileReader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 1afdb25346..9deca80d78 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -81,10 +81,10 @@ class LegacyProfileReader(ProfileReader): Logger.log("e", "Could not parse DictionaryOfDoom.json: %s", str(e)) return None - if "translations" not in dict_of_doom: - Logger.log("e", "Dictionary of Doom has no translations. Is it the correct JSON file?") + if "translation" not in dict_of_doom: + Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?") return None - for new_setting, old_setting_expression in dict_of_doom["translations"]: #Evaluate all new settings that would get a value from the translations. + for new_setting, old_setting_expression in dict_of_doom["translation"]: #Evaluate all new settings that would get a value from the translations. compiled = compile(old_setting_expression, new_setting, "eval") new_value = eval(compiled, {}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. profile.setSettingValue(new_setting, new_value) #Store the setting in the profile! From 99a13ba3aaee4307889bf221e765511c90f73ecc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:14:55 +0100 Subject: [PATCH 10/17] Fix getting settings from JSON file When reading a node of a JSON file, apparently it only lists the keys instead of key-value pairs. You have to get the values separately. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/LegacyProfileReader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 9deca80d78..8fecbac9bc 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -84,7 +84,8 @@ class LegacyProfileReader(ProfileReader): if "translation" not in dict_of_doom: Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?") return None - for new_setting, old_setting_expression in dict_of_doom["translation"]: #Evaluate all new settings that would get a value from the translations. + for new_setting in dict_of_doom["translation"]: #Evaluate all new settings that would get a value from the translations. + old_setting_expression = dict_of_doom["translation"][new_setting] compiled = compile(old_setting_expression, new_setting, "eval") new_value = eval(compiled, {}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. profile.setSettingValue(new_setting, new_value) #Store the setting in the profile! From 5358b700caf07c281886fb7747688386d6b1fd0d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:52:50 +0100 Subject: [PATCH 11/17] Fix ternary operator in import of support_enable The ternary operator of Python is different. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index c357c72bcd..9a37d126c0 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -38,7 +38,7 @@ "cool_min_layer_time": "cool_min_layer_time", "cool_min_speed": "cool_min_feedrate", "cool_lift_head": "cool_head_lift", - "support_enable": "support == \"None\" ? False : True", + "support_enable": "False if (support == \"None\") else True", "support_type": "support == \"Touching buildplate\" ? \"buildplate\" : \"everywhere\"", "support_angle": "support_angle", "support_xy_distance": "support_xy_distance", From bfa332e227c414197d0ee085089ed56c9a5c8045 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 09:54:35 +0100 Subject: [PATCH 12/17] Fix ternary operator in import of support_enable The ternary operator of Python is different. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index 9a37d126c0..9be77093de 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -39,7 +39,7 @@ "cool_min_speed": "cool_min_feedrate", "cool_lift_head": "cool_head_lift", "support_enable": "False if (support == \"None\") else True", - "support_type": "support == \"Touching buildplate\" ? \"buildplate\" : \"everywhere\"", + "support_type": "\"buildplate\" if (support == \"Touching buildplate\") else \"everywhere\"", "support_angle": "support_angle", "support_xy_distance": "support_xy_distance", "support_z_distance": "support_z_distance", From 0454b372430fb2ff23c09c616d09b40b5e5c100c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 10:00:00 +0100 Subject: [PATCH 13/17] Fix importing math to eval We expose only math, so it can do mathematical operations on the setting values when translating. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/LegacyProfileReader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 8fecbac9bc..5491b3ca18 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -3,6 +3,7 @@ import configparser #For reading the legacy profile INI files. import json #For reading the Dictionary of Doom. +import math #For mathematical operations included in the Dictionary of Doom. import os.path #For concatenating the path to the plugin and the relative path to the Dictionary of Doom. from UM.Application import Application #To get the machine manager to create the new profile in. @@ -87,7 +88,7 @@ class LegacyProfileReader(ProfileReader): for new_setting in dict_of_doom["translation"]: #Evaluate all new settings that would get a value from the translations. old_setting_expression = dict_of_doom["translation"][new_setting] compiled = compile(old_setting_expression, new_setting, "eval") - new_value = eval(compiled, {}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. + new_value = eval(compiled, {"math": math}, legacy_settings) #Pass the legacy settings as local variables to allow access to in the evaluation. profile.setSettingValue(new_setting, new_value) #Store the setting in the profile! return profile \ No newline at end of file From d2513f9bbb55212568b9e05aceef722810c6b1bf Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 10:03:34 +0100 Subject: [PATCH 14/17] Fix prime_tower_size import It was using math.sqrt incorrectly and also was trying to divide strings by each other, while they were floats. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index 9be77093de..e222486750 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -69,7 +69,7 @@ "magic_mesh_surface_mode": "simple_mode", "magic_spiralize": "spiralize", "prime_tower_enable": "wipe_tower", - "prime_tower_size": "sqrt(wipe_tower_volume / layer_height)", + "prime_tower_size": "math.sqrt(float(wipe_tower_volume) / float(layer_height))", "ooze_shield_enabled": "ooze_shield" } } \ No newline at end of file From 84613d99c46380b0f12efc33d8d07fabbf7bb1ac Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 10:07:34 +0100 Subject: [PATCH 15/17] Fix import of platform_adhesion This setting should never be set to None. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index e222486750..96a05b4fe0 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -45,7 +45,7 @@ "support_z_distance": "support_z_distance", "support_pattern": "support_type.lower()", "support_infill_rate": "support_fill_rate", - "platform_adhesion": "platform_adhesion.lower()", + "adhesion_type": "\"skirt\" if (platform_adhesion == \"None\") else platform_adhesion.lower()", "skirt_line_count": "skirt_line_count", "skirt_gap": "skirt_gap", "skirt_minimal_length": "skirt_minimal_length", From 68496349a92aa3434b1e9946ee8a4a7054b450dc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 10:19:28 +0100 Subject: [PATCH 16/17] Fix import of top and bottom thickness The legacy settings had a boolean for these, but in the current version is should just be a float. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index 96a05b4fe0..efbfcac7d4 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -8,8 +8,8 @@ "layer_height_0": "bottom_thickness", "shell_thickness": "wall_thickness", "top_bottom_thickness": "solid_layer_thickness", - "top_thickness": "solid_top", - "bottom_thickness": "solid_bottom", + "top_thickness": "0 if (solid_top == \"False\") else solid_layer_thickness", + "bottom_thickness": "0 if (solid_bottom == \"False\") else solid_layer_thickness", "skin_no_small_gaps_heuristic": "fix_horrible_extensive_stitching", "infill_sparse_density": "fill_density", "infill_overlap": "fill_overlap", From 482f0461fcdd49d5f42eff04920f14232e25303e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 18 Dec 2015 10:50:54 +0100 Subject: [PATCH 17/17] Add check for profile version The profile reader now checks whether the profile version is the same as the target version in the Dictionary of Doom. Contributes to issue CURA-37. --- plugins/LegacyProfileReader/DictionaryOfDoom.json | 2 +- plugins/LegacyProfileReader/LegacyProfileReader.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/LegacyProfileReader/DictionaryOfDoom.json b/plugins/LegacyProfileReader/DictionaryOfDoom.json index efbfcac7d4..6ff6dac4dd 100644 --- a/plugins/LegacyProfileReader/DictionaryOfDoom.json +++ b/plugins/LegacyProfileReader/DictionaryOfDoom.json @@ -1,6 +1,6 @@ { "source_version": "15.04", - "target_version": "2.1", + "target_version": 1, "translation": { "line_width": "nozzle_size", diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 5491b3ca18..5d89a85978 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -82,6 +82,14 @@ class LegacyProfileReader(ProfileReader): Logger.log("e", "Could not parse DictionaryOfDoom.json: %s", str(e)) return None + #Check the target version in the Dictionary of Doom with this application version. + if "target_version" not in dict_of_doom: + Logger.log("e", "Dictionary of Doom has no target version. Is it the correct JSON file?") + return None + if Profile.ProfileVersion != dict_of_doom["target_version"]: + Logger.log("e", "Dictionary of Doom of legacy profile reader (version %s) is not in sync with the profile version (version %s)!", dict_of_doom["target_version"], str(Profile.ProfileVersion)) + return None + if "translation" not in dict_of_doom: Logger.log("e", "Dictionary of Doom has no translation. Is it the correct JSON file?") return None