update_hashes.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """Compute sha256 hashes for files and update metadata.yaml."""
  2. from pathlib import Path
  3. import yaml
  4. from pooch.hashes import file_hash
  5. def _update_file_hash(
  6. file_path: Path,
  7. metadata_dict: dict,
  8. hash_key: str,
  9. ) -> None:
  10. """Update hash for a single file if the file exists and hash differs.
  11. Parameters
  12. ----------
  13. file_path : Path
  14. Path to the file to check and update hash for.
  15. metadata_dict : dict
  16. The metadata dictionary to update.
  17. hash_key : str
  18. The key in metadata_dict where the hash should be stored.
  19. """
  20. existing_hash = metadata_dict[hash_key]
  21. if file_path.exists():
  22. computed_hash = file_hash(file_path.as_posix())
  23. if existing_hash != computed_hash or existing_hash is None:
  24. metadata_dict[hash_key] = computed_hash
  25. print(
  26. f"Updated hash for {file_path.name}: "
  27. f"{existing_hash} -> {computed_hash}"
  28. )
  29. else:
  30. print(f"WARNING: Could not find {file_path}.")
  31. def _update_dataset_hashes(sample_metadata: dict, root_dir: Path) -> None:
  32. """Update all hashes (dataset, frame, video) for a single dataset.
  33. Parameters
  34. ----------
  35. sample_metadata : dict
  36. Metadata dictionary for a single sample dataset.
  37. root_dir : Path
  38. Root of the sample data directory.
  39. """
  40. filename = list(sample_metadata.keys())[0]
  41. sample_metadata = sample_metadata[filename]
  42. ds_type = sample_metadata["type"]
  43. # Update main dataset hash
  44. dataset_path = root_dir / ds_type / filename
  45. _update_file_hash(
  46. file_path=dataset_path,
  47. metadata_dict=sample_metadata,
  48. hash_key="sha256sum",
  49. )
  50. # Update frame hash if frame file exists
  51. frame_file_name = sample_metadata["frame"]["file_name"]
  52. if frame_file_name is not None:
  53. frame_path = root_dir / "frames" / frame_file_name
  54. _update_file_hash(
  55. file_path=frame_path,
  56. metadata_dict=sample_metadata["frame"],
  57. hash_key="sha256sum",
  58. )
  59. # Update video hash if video file exists
  60. video_file_name = sample_metadata["video"]["file_name"]
  61. if video_file_name is not None:
  62. video_path = root_dir / "videos" / video_file_name
  63. _update_file_hash(
  64. file_path=video_path,
  65. metadata_dict=sample_metadata["video"],
  66. hash_key="sha256sum",
  67. )
  68. def update_hashes_in_metadata(metadata_path: Path):
  69. """Update metadata.yaml with computed SHA256 hashes.
  70. Parameters
  71. ----------
  72. metadata_path : Path
  73. Path to the metadata.yaml file, which should be in the root
  74. of the sample data directory.
  75. """
  76. # Load existing metadata
  77. with open(metadata_path) as f:
  78. metadata = yaml.safe_load(f)
  79. # Get folder where metadata.yaml is located
  80. root_dir = metadata_path.parent
  81. # Update hashes for each dataset
  82. for sample_name in metadata:
  83. sample_metadata = {sample_name: metadata[sample_name]}
  84. _update_dataset_hashes(sample_metadata, root_dir)
  85. # Save updated metadata
  86. with open(metadata_path, 'w') as f:
  87. yaml.dump(
  88. metadata,
  89. f,
  90. default_flow_style=False,
  91. sort_keys=False,
  92. )
  93. print("Metadata updated successfully!")
  94. if __name__ == "__main__":
  95. metadata_path = Path.cwd() / "metadata.yaml"
  96. update_hashes_in_metadata(metadata_path)