Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

versionlist.py 7.4 KB

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