mtreeproxy.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from typing import (
  2. cast,
  3. Any,
  4. Iterable,
  5. Optional,
  6. Tuple
  7. )
  8. from dataladmetadatamodel.mappableobject import MappableObject
  9. from dataladmetadatamodel.mapper.gitmapper.metadatamapper import MetadataGitMapper
  10. from dataladmetadatamodel.mapper.gitmapper.objectreference import (
  11. add_tree_reference,
  12. GitReference,
  13. )
  14. from dataladmetadatamodel.metadatapath import MetadataPath
  15. from dataladmetadatamodel.mtreenode import MTreeNode
  16. from dataladmetadatamodel.mapper.reference import Reference
  17. class MTreeProxy:
  18. """
  19. Base class for all classes that use MTreeNode internally,
  20. but are not themselves mappable. Those classes typically
  21. require a stored tree, but do not add additional
  22. "data-fields", but just convenience methods. Examples are
  23. "DatasetTree" and "FileTree". Still those classes are
  24. contained within other mappable objects and therefore should
  25. behave like a mappable object.
  26. This class proxies the common MappableObject-interface calls
  27. to the underlying MTreeNode object.
  28. # TODO: this could probably be a mixin.
  29. """
  30. def __init__(self,
  31. leaf_class: Any,
  32. mtree: Optional[MTreeNode] = None,
  33. realm: Optional[str] = None,
  34. reference: Optional[Reference] = None):
  35. assert isinstance(mtree, (type(None), MTreeNode))
  36. assert isinstance(reference, (type(None), Reference))
  37. if mtree is None:
  38. self.mtree = MTreeNode(leaf_class=leaf_class,
  39. realm=realm,
  40. reference=reference)
  41. else:
  42. assert mtree.leaf_class == leaf_class
  43. self.mtree = mtree
  44. def __contains__(self, path: MetadataPath) -> bool:
  45. return self.mtree.get_object_at_path(path) is not None
  46. def ensure_mapped(self) -> bool:
  47. return self.mtree.ensure_mapped()
  48. def read_in(self, backend_type="git") -> MappableObject:
  49. self.mtree.read_in(backend_type)
  50. return cast(MappableObject, self)
  51. def write_out(self,
  52. destination: Optional[str] = None,
  53. backend_type: str = "git",
  54. force_write: bool = False) -> Reference:
  55. # Since a file tree might contain a large number
  56. # of metadata entries and since each entry requires
  57. # two blobs to be written, we use a write-cache.
  58. # TODO: ugly:
  59. from .filetree import FileTree
  60. cache_destination = destination or self.mtree.realm
  61. if isinstance(self, FileTree):
  62. MetadataGitMapper.cache_realm(cache_destination)
  63. reference = self.mtree.write_out(destination,
  64. backend_type,
  65. force_write)
  66. if isinstance(self, FileTree):
  67. MetadataGitMapper.flush_realm(cache_destination)
  68. if not reference.is_none_reference():
  69. add_tree_reference(GitReference.TREES,
  70. reference.location)
  71. return reference
  72. def purge(self):
  73. return self.mtree.purge()
  74. def is_saved_on(self, destination: str):
  75. return self.mtree.is_saved_on(destination)
  76. def deepcopy(self,
  77. new_mapper_family: Optional[str] = None,
  78. new_destination: Optional[str] = None,
  79. **kwargs) -> "MTreeProxy":
  80. return type(self)(self.mtree.deepcopy(new_mapper_family,
  81. new_destination,
  82. **kwargs))
  83. def get_paths_recursive(self,
  84. show_intermediate: Optional[bool] = False
  85. ) -> Iterable[Tuple[MetadataPath, MappableObject]]:
  86. yield from self.mtree.get_paths_recursive(show_intermediate)