versionlist.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. from typing import (
  2. Dict,
  3. Iterable,
  4. Optional,
  5. Tuple,
  6. Union
  7. )
  8. from dataladmetadatamodel.datasettree import DatasetTree
  9. from dataladmetadatamodel.mappableobject import MappableObject
  10. from dataladmetadatamodel.metadatapath import MetadataPath
  11. from dataladmetadatamodel.metadatarootrecord import MetadataRootRecord
  12. from dataladmetadatamodel.mapper.reference import Reference
  13. class VersionRecord:
  14. def __init__(self,
  15. time_stamp: str,
  16. path: Optional[MetadataPath],
  17. element: Union[DatasetTree, MetadataRootRecord]):
  18. assert isinstance(time_stamp, str)
  19. assert isinstance(path, (type(None), MetadataPath))
  20. assert isinstance(element, (DatasetTree, MetadataRootRecord))
  21. self.time_stamp = time_stamp
  22. self.path = path or MetadataPath("")
  23. self.element = element
  24. def deepcopy(self,
  25. new_mapper_family: Optional[str] = None,
  26. new_destination: Optional[str] = None
  27. ) -> "VersionRecord":
  28. return VersionRecord(
  29. self.time_stamp,
  30. self.path,
  31. self.element.deepcopy(
  32. new_mapper_family,
  33. new_destination))
  34. class VersionList(MappableObject):
  35. def __init__(self,
  36. initial_set: Optional[Dict[str, VersionRecord]] = None,
  37. reference: Optional[Reference] = None):
  38. assert isinstance(initial_set, (type(None), dict))
  39. assert isinstance(reference, (type(None), Reference))
  40. super().__init__(reference)
  41. self.version_set: Dict[str, VersionRecord] = initial_set or dict()
  42. def purge_impl(self):
  43. for version, version_record in self.version_set.items():
  44. version_record.element.purge()
  45. self.version_set = dict()
  46. def get_modifiable_sub_objects_impl(self) -> Iterable[MappableObject]:
  47. yield from map(
  48. lambda version_record: version_record.element,
  49. self.version_set.values())
  50. def _get_version_record(self, primary_data_version) -> VersionRecord:
  51. return self.version_set[primary_data_version]
  52. def versions(self) -> Iterable:
  53. return self.version_set.keys()
  54. def get_versioned_element(self,
  55. primary_data_version: str
  56. ) -> Tuple[str, MetadataPath, MappableObject]:
  57. """
  58. Get the dataset tree or metadata root record,
  59. its timestamp and path for the given version.
  60. If it is not mapped yet, it will be mapped.
  61. """
  62. version_record = self._get_version_record(primary_data_version)
  63. version_record.element.read_in()
  64. return (
  65. version_record.time_stamp,
  66. version_record.path,
  67. version_record.element)
  68. def get_versioned_elements(self
  69. ) -> Iterable[Tuple[str, Tuple[str, MetadataPath, MappableObject]]]:
  70. """
  71. Get an iterable of all versions and their records
  72. """
  73. for version, version_record in self.version_set.items():
  74. yield version, (
  75. version_record.time_stamp,
  76. version_record.path,
  77. version_record.element)
  78. def set_versioned_element(self,
  79. primary_data_version: str,
  80. time_stamp: str,
  81. path: MetadataPath,
  82. element: Union[DatasetTree, MetadataRootRecord]):
  83. """
  84. Set a new or updated dataset tree.
  85. Existing references are deleted.
  86. The entry is marked as dirty.
  87. """
  88. self.touch()
  89. self.version_set[primary_data_version] = VersionRecord(
  90. time_stamp,
  91. path,
  92. element)
  93. def unget_versioned_element(self,
  94. primary_data_version: str,
  95. new_destination: Optional[str] = None):
  96. """
  97. Remove a metadata record from memory. First, persist the
  98. current status via save_object ---which will write it to
  99. the backend, if it was changed or--- then purge it
  100. from memory.
  101. """
  102. version_record = self.version_set[primary_data_version]
  103. version_record.element.write_out(new_destination)
  104. version_record.element.purge()
  105. def deepcopy_impl(self,
  106. new_mapper_family: Optional[str] = None,
  107. new_destination: Optional[str] = None,
  108. **kwargs
  109. ) -> "VersionList":
  110. path_prefix = kwargs.get("path_prefix", MetadataPath(""))
  111. copied_version_list = VersionList()
  112. for primary_data_version, version_record in self.version_set.items():
  113. copied_version_list.set_versioned_element(
  114. primary_data_version,
  115. version_record.time_stamp,
  116. path_prefix / version_record.path,
  117. version_record.element.deepcopy(new_mapper_family,
  118. new_destination))
  119. copied_version_list.write_out(new_destination)
  120. copied_version_list.purge()
  121. return copied_version_list
  122. class TreeVersionList(VersionList):
  123. """
  124. Thin wrapper around version list to support tree-version list
  125. specific mapping, for example in the git mapper, which will
  126. update a reference, if mapping an TreeVersionList instance.
  127. """
  128. def get_dataset_tree(self,
  129. primary_data_version: str
  130. ) -> Tuple[str, DatasetTree]:
  131. time_stamp, _, dataset_tree = super().get_versioned_element(
  132. primary_data_version)
  133. assert isinstance(dataset_tree, DatasetTree)
  134. return time_stamp, dataset_tree
  135. def set_dataset_tree(self,
  136. primary_data_version: str,
  137. time_stamp: str,
  138. dataset_tree: DatasetTree
  139. ):
  140. self.touch()
  141. return super().set_versioned_element(
  142. primary_data_version,
  143. time_stamp,
  144. MetadataPath(""),
  145. dataset_tree)
  146. def unget_dataset_tree(self,
  147. primary_data_version: str,
  148. new_destination: str):
  149. assert isinstance(primary_data_version, str)
  150. assert isinstance(new_destination, str)
  151. super().unget_versioned_element(primary_data_version,
  152. new_destination)
  153. def deepcopy_impl(self,
  154. new_mapper_family: Optional[str] = None,
  155. new_destination: Optional[str] = None,
  156. **kwargs
  157. ) -> "TreeVersionList":
  158. path_prefix = kwargs.get("path_prefix", MetadataPath(""))
  159. copied_version_list = TreeVersionList()
  160. for primary_data_version, version_record in self.version_set.items():
  161. copied_version_list.set_versioned_element(
  162. primary_data_version,
  163. version_record.time_stamp,
  164. path_prefix / version_record.path,
  165. version_record.element.deepcopy(
  166. new_mapper_family,
  167. new_destination))
  168. copied_version_list.write_out(new_destination)
  169. copied_version_list.purge()
  170. return copied_version_list