123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- # Copyright (c) 2018 Ultimaker B.V.
- # Cura is released under the terms of the LGPLv3 or higher.
- import configparser #To get version numbers from config files.
- import io
- import os
- import os.path
- from typing import Dict, List, Optional, Tuple
- from UM.Resources import Resources
- from UM.VersionUpgrade import VersionUpgrade # Superclass of the plugin.
- import UM.VersionUpgrade
- class VersionUpgrade22to24(VersionUpgrade):
- def upgradeMachineInstance(self, serialised: str, filename: str) -> Optional[Tuple[List[str], List[str]]]:
- # All of this is needed to upgrade custom variant machines from old Cura to 2.4 where
- # `definition_changes` instance container has been introduced. Variant files which
- # look like the the handy work of the old machine settings plugin are converted directly
- # on disk.
- config = configparser.ConfigParser(interpolation = None)
- config.read_string(serialised) # Read the input string as config file.
- if config.get("metadata", "type") == "definition_changes":
- # This is not a container stack, don't upgrade it here
- return None
- config.set("general", "version", "3")
- container_list = [] # type: List[str]
- if config.has_section("containers"):
- for index, container_id in config.items("containers"):
- container_list.append(container_id)
- elif config.has_option("general", "containers"):
- containers = config.get("general", "containers")
- container_list = containers.split(",")
- user_variants = self.__getUserVariants()
- name_path_dict = {}
- for variant in user_variants:
- name_path_dict[variant["name"]] = variant["path"]
- user_variant_names = set(container_list).intersection(name_path_dict.keys())
- if len(user_variant_names):
- # One of the user defined variants appears in the list of containers in the stack.
- for variant_name in user_variant_names: # really there should just be one variant to convert.
- config_name = self.__convertVariant(name_path_dict[variant_name])
- # Change the name of variant and insert empty_variant into the stack.
- new_container_list = []
- for item in container_list:
- if not item: # the last item may be an empty string
- continue
- if item == variant_name:
- new_container_list.append("empty_variant")
- new_container_list.append(config_name)
- else:
- new_container_list.append(item)
- container_list = new_container_list
- if not config.has_section("containers"):
- config.add_section("containers")
- config.remove_option("general", "containers")
- for idx, _ in enumerate(container_list):
- config.set("containers", str(idx), container_list[idx])
- output = io.StringIO()
- config.write(output)
- return [filename], [output.getvalue()]
- def __convertVariant(self, variant_path: str) -> str:
- # Copy the variant to the machine_instances/*_settings.inst.cfg
- variant_config = configparser.ConfigParser(interpolation = None)
- with open(variant_path, "r", encoding = "utf-8") as fhandle:
- variant_config.read_file(fhandle)
- config_name = "Unknown Variant"
- if variant_config.has_section("general") and variant_config.has_option("general", "name"):
- config_name = variant_config.get("general", "name")
- if config_name.endswith("_variant"):
- config_name = config_name[:-len("_variant")] + "_settings"
- variant_config.set("general", "name", config_name)
- if not variant_config.has_section("metadata"):
- variant_config.add_section("metadata")
- variant_config.set("metadata", "type", "definition_changes")
- resource_path = Resources.getDataStoragePath()
- machine_instances_dir = os.path.join(resource_path, "machine_instances")
- if variant_path.endswith("_variant.inst.cfg"):
- variant_path = variant_path[:-len("_variant.inst.cfg")] + "_settings.inst.cfg"
- with open(os.path.join(machine_instances_dir, os.path.basename(variant_path)), "w", encoding = "utf-8") as fp:
- variant_config.write(fp)
- return config_name
- def __getUserVariants(self) -> List[Dict[str, str]]:
- resource_path = Resources.getDataStoragePath()
- variants_dir = os.path.join(resource_path, "variants")
- result = []
- for entry in os.scandir(variants_dir):
- if entry.name.endswith(".inst.cfg") and entry.is_file():
- config = configparser.ConfigParser(interpolation = None)
- with open(entry.path, "r", encoding = "utf-8") as fhandle:
- config.read_file(fhandle)
- if config.has_section("general") and config.has_option("general", "name"):
- result.append( { "path": entry.path, "name": config.get("general", "name") } )
- return result
- def upgradeExtruderTrain(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
- config = configparser.ConfigParser(interpolation = None)
- config.read_string(serialised) # Read the input string as config file.
- config.set("general", "version", "3") # Just bump the version number. That is all we need for now.
- output = io.StringIO()
- config.write(output)
- return [filename], [output.getvalue()]
- def upgradePreferences(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
- config = configparser.ConfigParser(interpolation = None)
- config.read_string(serialised)
- if not config.has_section("general"):
- raise UM.VersionUpgrade.FormatException("No \"general\" section.")
- # Make z_seam_x and z_seam_y options visible. In a clean 2.4 they are visible by default.
- if config.has_option("general", "visible_settings"):
- visible_settings = config.get("general", "visible_settings")
- visible_set = set(visible_settings.split(";"))
- visible_set.add("z_seam_x")
- visible_set.add("z_seam_y")
- config.set("general", "visible_settings", ";".join(visible_set))
- config.set("general", "version", value="4")
- output = io.StringIO()
- config.write(output)
- return [filename], [output.getvalue()]
- def upgradeQuality(self, serialised: str, filename: str) -> Tuple[List[str], List[str]]:
- config = configparser.ConfigParser(interpolation = None)
- config.read_string(serialised) # Read the input string as config file.
- config.set("metadata", "type", "quality_changes") # Update metadata/type to quality_changes
- config.set("general", "version", "2") # Just bump the version number. That is all we need for now.
- output = io.StringIO()
- config.write(output)
- return [filename], [output.getvalue()]
- def getCfgVersion(self, serialised: str) -> int:
- 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
|