VersionUpgrade.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # Copyright (c) 2017 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import configparser #To get version numbers from config files.
  4. import os
  5. import os.path
  6. import io
  7. from UM.Resources import Resources
  8. from UM.VersionUpgrade import VersionUpgrade # Superclass of the plugin.
  9. import UM.VersionUpgrade
  10. class VersionUpgrade22to24(VersionUpgrade):
  11. def upgradeMachineInstance(self, serialised, filename):
  12. # All of this is needed to upgrade custom variant machines from old Cura to 2.4 where
  13. # `definition_changes` instance container has been introduced. Variant files which
  14. # look like the the handy work of the old machine settings plugin are converted directly
  15. # on disk.
  16. config = configparser.ConfigParser(interpolation = None)
  17. config.read_string(serialised) # Read the input string as config file.
  18. if config.get("metadata", "type") == "definition_changes":
  19. # This is not a container stack, don't upgrade it here
  20. return
  21. config.set("general", "version", "3")
  22. container_list = []
  23. if config.has_section("containers"):
  24. for index, container_id in config.items("containers"):
  25. container_list.append(container_id)
  26. elif config.has_option("general", "containers"):
  27. containers = config.get("general", "containers")
  28. container_list = containers.split(",")
  29. user_variants = self.__getUserVariants()
  30. name_path_dict = {}
  31. for variant in user_variants:
  32. name_path_dict[variant.get("name")] = variant.get("path")
  33. user_variant_names = set(container_list).intersection(name_path_dict.keys())
  34. if len(user_variant_names):
  35. # One of the user defined variants appears in the list of containers in the stack.
  36. for variant_name in user_variant_names: # really there should just be one variant to convert.
  37. config_name = self.__convertVariant(name_path_dict.get(variant_name))
  38. # Change the name of variant and insert empty_variant into the stack.
  39. new_container_list = []
  40. for item in container_list:
  41. if not item: # the last item may be an empty string
  42. continue
  43. if item == variant_name:
  44. new_container_list.append("empty_variant")
  45. new_container_list.append(config_name)
  46. else:
  47. new_container_list.append(item)
  48. container_list = new_container_list
  49. if not config.has_section("containers"):
  50. config.add_section("containers")
  51. config.remove_option("general", "containers")
  52. for index in range(len(container_list)):
  53. config.set("containers", str(index), container_list[index])
  54. output = io.StringIO()
  55. config.write(output)
  56. return [filename], [output.getvalue()]
  57. def __convertVariant(self, variant_path):
  58. # Copy the variant to the machine_instances/*_settings.inst.cfg
  59. variant_config = configparser.ConfigParser(interpolation=None)
  60. with open(variant_path, "r", encoding = "utf-8") as fhandle:
  61. variant_config.read_file(fhandle)
  62. config_name = "Unknown Variant"
  63. if variant_config.has_section("general") and variant_config.has_option("general", "name"):
  64. config_name = variant_config.get("general", "name")
  65. if config_name.endswith("_variant"):
  66. config_name = config_name[:-len("_variant")] + "_settings"
  67. variant_config.set("general", "name", config_name)
  68. if not variant_config.has_section("metadata"):
  69. variant_config.add_section("metadata")
  70. variant_config.set("metadata", "type", "definition_changes")
  71. resource_path = Resources.getDataStoragePath()
  72. machine_instances_dir = os.path.join(resource_path, "machine_instances")
  73. if variant_path.endswith("_variant.inst.cfg"):
  74. variant_path = variant_path[:-len("_variant.inst.cfg")] + "_settings.inst.cfg"
  75. with open(os.path.join(machine_instances_dir, os.path.basename(variant_path)), "w") as fp:
  76. variant_config.write(fp)
  77. return config_name
  78. def __getUserVariants(self):
  79. resource_path = Resources.getDataStoragePath()
  80. variants_dir = os.path.join(resource_path, "variants")
  81. result = []
  82. for entry in os.scandir(variants_dir):
  83. if entry.name.endswith('.inst.cfg') and entry.is_file():
  84. config = configparser.ConfigParser(interpolation = None)
  85. with open(entry.path, "r") as fhandle:
  86. config.read_file(fhandle)
  87. if config.has_section("general") and config.has_option("general", "name"):
  88. result.append( { "path": entry.path, "name": config.get("general", "name") } )
  89. return result
  90. def upgradeExtruderTrain(self, serialised, filename):
  91. config = configparser.ConfigParser(interpolation = None)
  92. config.read_string(serialised) # Read the input string as config file.
  93. config.set("general", "version", "3") # Just bump the version number. That is all we need for now.
  94. output = io.StringIO()
  95. config.write(output)
  96. return [filename], [output.getvalue()]
  97. def upgradePreferences(self, serialised, filename):
  98. config = configparser.ConfigParser(interpolation = None)
  99. config.read_string(serialised)
  100. if not config.has_section("general"):
  101. raise UM.VersionUpgrade.FormatException("No \"general\" section.")
  102. # Make z_seam_x and z_seam_y options visible. In a clean 2.4 they are visible by default.
  103. if config.has_option("general", "visible_settings"):
  104. visible_settings = config.get("general", "visible_settings")
  105. visible_set = set(visible_settings.split(";"))
  106. visible_set.add("z_seam_x")
  107. visible_set.add("z_seam_y")
  108. config.set("general", "visible_settings", ";".join(visible_set))
  109. config.set("general", "version", value="4")
  110. output = io.StringIO()
  111. config.write(output)
  112. return [filename], [output.getvalue()]
  113. def upgradeQuality(self, serialised, filename):
  114. config = configparser.ConfigParser(interpolation = None)
  115. config.read_string(serialised) # Read the input string as config file.
  116. config.set("metadata", "type", "quality_changes") # Update metadata/type to quality_changes
  117. config.set("general", "version", "2") # Just bump the version number. That is all we need for now.
  118. output = io.StringIO()
  119. config.write(output)
  120. return [filename], [output.getvalue()]
  121. def getCfgVersion(self, serialised):
  122. parser = configparser.ConfigParser(interpolation = None)
  123. parser.read_string(serialised)
  124. format_version = int(parser.get("general", "version")) #Explicitly give an exception when this fails. That means that the file format is not recognised.
  125. setting_version = int(parser.get("metadata", "setting_version", fallback = 0))
  126. return format_version * 1000000 + setting_version