CuraProfileReader.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # Copyright (c) 2016 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import configparser
  4. from UM.PluginRegistry import PluginRegistry
  5. from UM.Logger import Logger
  6. from UM.Settings.InstanceContainer import InstanceContainer # The new profile to make.
  7. from cura.ProfileReader import ProfileReader
  8. import zipfile
  9. ## A plugin that reads profile data from Cura profile files.
  10. #
  11. # It reads a profile from a .curaprofile file, and returns it as a profile
  12. # instance.
  13. class CuraProfileReader(ProfileReader):
  14. ## Initialises the cura profile reader.
  15. # This does nothing since the only other function is basically stateless.
  16. def __init__(self):
  17. super().__init__()
  18. ## Reads a cura profile from a file and returns it.
  19. #
  20. # \param file_name The file to read the cura profile from.
  21. # \return The cura profile that was in the file, if any. If the file could
  22. # not be read or didn't contain a valid profile, \code None \endcode is
  23. # returned.
  24. def read(self, file_name):
  25. try:
  26. with zipfile.ZipFile(file_name, "r") as archive:
  27. results = []
  28. for profile_id in archive.namelist():
  29. with archive.open(profile_id) as f:
  30. serialized = f.read()
  31. profile = self._loadProfile(serialized.decode("utf-8"), profile_id)
  32. if profile is not None:
  33. results.append(profile)
  34. return results
  35. except zipfile.BadZipFile:
  36. # It must be an older profile from Cura 2.1.
  37. with open(file_name, encoding="utf-8") as fhandle:
  38. serialized = fhandle.read()
  39. return [self._loadProfile(serialized, profile_id) for serialized, profile_id in self._upgradeProfile(serialized, file_name)]
  40. ## Convert a profile from an old Cura to this Cura if needed.
  41. #
  42. # \param serialized \type{str} The profile data to convert in the serialized on-disk format.
  43. # \param profile_id \type{str} The name of the profile.
  44. # \return \type{List[Tuple[str,str]]} List of serialized profile strings and matching profile names.
  45. def _upgradeProfile(self, serialized, profile_id):
  46. parser = configparser.ConfigParser(interpolation=None)
  47. parser.read_string(serialized)
  48. if not "general" in parser:
  49. Logger.log("w", "Missing required section 'general'.")
  50. return []
  51. if not "version" in parser["general"]:
  52. Logger.log("w", "Missing required 'version' property")
  53. return []
  54. version = int(parser["general"]["version"])
  55. if InstanceContainer.Version != version:
  56. name = parser["general"]["name"]
  57. return self._upgradeProfileVersion(serialized, name, version)
  58. else:
  59. return [(serialized, profile_id)]
  60. ## Load a profile from a serialized string.
  61. #
  62. # \param serialized \type{str} The profile data to read.
  63. # \param profile_id \type{str} The name of the profile.
  64. # \return \type{InstanceContainer|None}
  65. def _loadProfile(self, serialized, profile_id):
  66. # Create an empty profile.
  67. profile = InstanceContainer(profile_id)
  68. profile.addMetaDataEntry("type", "quality_changes")
  69. try:
  70. profile.deserialize(serialized)
  71. except Exception as e: # Parsing error. This is not a (valid) Cura profile then.
  72. Logger.log("e", "Error while trying to parse profile: %s", str(e))
  73. return None
  74. return profile
  75. ## Upgrade a serialized profile to the current profile format.
  76. #
  77. # \param serialized \type{str} The profile data to convert.
  78. # \param profile_id \type{str} The name of the profile.
  79. # \param source_version \type{int} The profile version of 'serialized'.
  80. # \return \type{List[Tuple[str,str]]} List of serialized profile strings and matching profile names.
  81. def _upgradeProfileVersion(self, serialized, profile_id, source_version):
  82. converter_plugins = PluginRegistry.getInstance().getAllMetaData(filter={"version_upgrade": {} }, active_only=True)
  83. source_format = ("profile", source_version)
  84. profile_convert_funcs = [plugin["version_upgrade"][source_format][2] for plugin in converter_plugins
  85. if source_format in plugin["version_upgrade"] and plugin["version_upgrade"][source_format][1] == InstanceContainer.Version]
  86. if not profile_convert_funcs:
  87. return []
  88. filenames, outputs = profile_convert_funcs[0](serialized, profile_id)
  89. if filenames is None and outputs is None:
  90. return []
  91. return list(zip(outputs, filenames))