def decode_parsed(self, json_as_dict: dict) -> IrodsMetadata: if not isinstance(json_as_dict, List): return super().decode(json_as_dict) irods_metadata = IrodsMetadata() for item in json_as_dict: assert isinstance(item, dict) attribute = item[BATON_AVU_ATTRIBUTE_PROPERTY] value = item[BATON_AVU_VALUE_PROPERTY] irods_metadata.add(attribute, value) return irods_metadata
def combine_metadata(metadata_collection: Iterable[IrodsMetadata]) -> IrodsMetadata: """ Combines n metadata objects into a single metadata object. Key values are merged, duplicate values are removed. :param metadata_collection: the collection of metadata to combine :return: the combined metadata """ combined = IrodsMetadata() for metadata in metadata_collection: for key, values in metadata.items(): for value in values: combined.add(key, value) return combined
def setUp(self): self.test_with_baton = TestWithBaton(baton_setup=BATON_SETUP) self.test_with_baton.setup() self.setup_helper = SetupHelper(self.test_with_baton.icommands_location) self.mapper = self.create_mapper() self.metadata = IrodsMetadata({"key_1": {"value_1", "value_2"}, "key_2": {"value_3"}}) self._entity = None self._entities = None
def default(self, irods_metadata: IrodsMetadata) -> PrimitiveJsonSerializableType: if not isinstance(irods_metadata, IrodsMetadata): return super().default(irods_metadata) avus = [] for key, values in irods_metadata.items(): for value in values: avus.append({ BATON_AVU_ATTRIBUTE_PROPERTY: key, BATON_AVU_VALUE_PROPERTY: value }) return avus
class TestIrodsMetadata(unittest.TestCase): """ Tests for `IrodsMetadata`. """ def setUp(self): self.metadata = IrodsMetadata({"attribute_a": {"value_1"}, "attribute_b": {"value_b"}}) def test_equal(self): self.assertEqual(copy.deepcopy(self.metadata), self.metadata) def test_add_when_key_does_not_exists(self): self.metadata.add("key", "value") self.assertEqual(self.metadata["key"], {"value"}) def test_add_when_key_exists(self): self.metadata["key"] = {"value_1"} self.metadata.add("key", "value_2") self.assertEqual(self.metadata["key"], {"value_1", "value_2"}) def test_get_when_default(self): default = object() value = self.metadata.get("not_set", default=default) self.assertEqual(value, default)
def setUp(self): self.metadata = IrodsMetadata({"attribute_a": {"value_1"}, "attribute_b": {"value_b"}})
def setUp(self): self.path = "/path" self.data_object = DataObject(self.path, metadata=IrodsMetadata(), replicas={})
class _TestBatonIrodsEntityMetadataMapper(unittest.TestCase): """ Tests for `_BatonIrodsMetadataMapper`. """ @abstractmethod def create_mapper(self) -> _BatonIrodsMetadataMapper: """ Creates a mapper to test with. :return: the created mapper """ @abstractmethod def create_irods_entity(self, name: str, metadata: IrodsMetadata=IrodsMetadata()) -> IrodsEntity: """ Creates an iRODS entity to test with :param name: the name of the entity to create :param metadata: the metadata to give to the entity :return: the created entity """ def setUp(self): self.test_with_baton = TestWithBaton(baton_setup=BATON_SETUP) self.test_with_baton.setup() self.setup_helper = SetupHelper(self.test_with_baton.icommands_location) self.mapper = self.create_mapper() self.metadata = IrodsMetadata({"key_1": {"value_1", "value_2"}, "key_2": {"value_3"}}) self._entity = None self._entities = None def tearDown(self): self.test_with_baton.tear_down() @property def entity(self) -> IrodsEntity: """ Lazily creates the test entity (prevents spending time creating unused entities in iRODS). :return: an example entity """ if self._entity is None: self._entity = self.create_irods_entity("%s_entity" % NAMES[0]) return self._entity @property def entities(self) -> List[IrodsEntity]: """ Lazily creates a set of test entities (prevents spending time creating unused entities in iRODS). :return: an example collection of entities """ if self._entities is None: self._entities = [self.create_irods_entity(name) for name in NAMES] return self._entities def test_get_all_with_no_paths(self): self.assertEqual(self.mapper.get_all([]), []) def test_get_all_with_single_path_that_is_invalid(self): self.assertRaises(FileNotFoundError, self.mapper.get_all, "/invalid") def test_get_all_with_single_path(self): entity = self.create_irods_entity(NAMES[0], self.metadata) self.assertEqual(self.mapper.get_all(entity.path), self.metadata) def test_get_all_with_multiple_paths_including_an_invalid_path(self): self.assertRaises(FileNotFoundError, self.mapper.get_all, [self.entity.path, "/invalid"]) def test_get_all_with_multiple_paths(self): entities = [self.create_irods_entity(name, self.metadata) for name in NAMES] paths = [entity.path for entity in entities] self.assertEqual(self.mapper.get_all(paths), [entity.metadata for entity in entities]) def test_add_with_single_path_that_is_invalid(self): self.assertRaises(FileNotFoundError, self.mapper.add, "/invalid", self.metadata) def test_add_with_single_path(self): self.mapper.add(self.entity.path, self.metadata) self.assertEqual(self.mapper.get_all(self.entity.path), self.metadata) def test_add_with_multiple_paths_including_an_invalid_path(self): self.assertRaises(FileNotFoundError, self.mapper.add, [self.entity.path, "/invalid"], self.metadata) def test_add_with_multiple_paths_but_invalid_number_of_associated_metadata(self): paths = [entity.path for entity in self.entities] assert len(paths) > 2 self.assertRaises(ValueError, self.mapper.add, paths, [self.metadata, self.metadata]) def test_add_with_multiple_paths_and_single_metadata(self): paths = [entity.path for entity in self.entities] self.mapper.add(paths, self.metadata) self.assertEqual(self.mapper.get_all(paths), [self.metadata for _ in self.entities]) def test_add_with_multiple_paths_and_multiple_metadata(self): paths = [entity.path for entity in self.entities] metadata = [self.metadata for _ in range(len(self.entities))] self.mapper.add(paths, metadata) self.assertEqual(self.mapper.get_all(paths), metadata) def test_add_no_metadata(self): self.mapper.add(self.entity.path, IrodsMetadata()) self.assertEqual(self.mapper.get_all(self.entity.path), IrodsMetadata()) def test_add_metadata_with_same_key(self): entity = self.create_irods_entity(NAMES[0], self.metadata) del self.metadata["key_1"] assert len(self.metadata) == 1 self.assertRaises(KeyError, self.mapper.add, entity.path, self.metadata) def test_add_adds_metadata(self): entity = self.create_irods_entity(NAMES[0], self.metadata) additional_metadata = IrodsMetadata({"other": {"values"}}) self.mapper.add(entity.path, additional_metadata) self.assertEqual(self.mapper.get_all(entity.path), IrodsMetadata({**dict(entity.metadata), **dict(additional_metadata)})) def test_add_appends_if_key_exists_and_not_same_value(self): values = ["value_1", "value_2"] key = "key" entity = self.create_irods_entity(NAMES[0], IrodsMetadata({key: {values[0]}})) self.mapper.add(entity.path, IrodsMetadata({key: {values[1]}})) self.assertEqual(IrodsMetadata({key: {values[0], values[1]}}), self.mapper.get_all(entity.path)) def test_set_with_no_paths(self): self.mapper.set([], self.metadata) def test_set_with_single_path_that_is_invalid(self): self.assertRaises(FileNotFoundError, self.mapper.set, "/invalid", self.metadata) def test_set_with_single_path(self): self.mapper.set(self.entity.path, self.metadata) self.assertEqual(self.mapper.get_all(self.entity.path), self.metadata) def test_set_with_multiple_paths_including_an_invalid_path(self): self.assertRaises(FileNotFoundError, self.mapper.set, [self.entity.path, "/invalid"], self.metadata) def test_set_with_multiple_paths_and_single_metadata(self): paths = [entity.path for entity in self.entities] self.mapper.set(paths, self.metadata) self.assertEqual(self.mapper.get_all(paths), [self.metadata for _ in self.entities]) def test_set_with_multiple_paths_and_multiple_metadata(self): paths = [entity.path for entity in self.entities] metadata = [self.metadata for _ in range(len(self.entities))] self.mapper.set(paths, metadata) self.assertEqual(self.mapper.get_all(paths), metadata) def test_set_overrides_existing_metadata(self): overriden_key = list(self.metadata.keys())[0] value = {"new_value"} entity_1 = self.create_irods_entity(NAMES[0], self.metadata) del self.metadata[overriden_key] entity_2 = self.create_irods_entity(NAMES[1], self.metadata) self.mapper.set([entity_1.path, entity_2.path], IrodsMetadata({overriden_key: value})) self.metadata[overriden_key] = value self.assertEqual(self.mapper.get_all(entity_1.path), self.metadata) self.assertEqual(self.mapper.get_all(entity_2.path), self.metadata) def test_remove_with_no_paths(self): self.mapper.remove([], self.metadata) def test_remove_with_single_path_that_is_invalid(self): self.assertRaises(FileNotFoundError, self.mapper.remove, "/invalid", self.metadata) def test_remove_with_single_path(self): entity = self.create_irods_entity(NAMES[0], self.metadata) self.mapper.remove(entity.path, self.metadata) self.assertEqual(self.mapper.get_all(entity.path), IrodsMetadata()) def test_remove_with_multiple_paths_including_an_invalid_path(self): entity = self.create_irods_entity(NAMES[0], self.metadata) self.assertRaises(FileNotFoundError, self.mapper.remove, [entity.path, "/invalid"], self.metadata) def test_remove_with_multiple_paths_and_single_metadata(self): entities = [self.create_irods_entity(name, self.metadata) for name in NAMES] paths = [entity.path for entity in entities] self.mapper.remove(paths, self.metadata) self.assertEqual(self.mapper.get_all(paths), [IrodsMetadata() for _ in paths]) def test_remove_with_multiple_paths_and_multiple_metadata(self): entities = [self.create_irods_entity(name, self.metadata) for name in NAMES] paths = [entity.path for entity in entities] metadata = [entity.metadata for entity in entities] self.mapper.remove(paths, metadata) self.assertEqual(self.mapper.get_all(paths), [IrodsMetadata() for _ in paths]) def test_remove_unset_metadata(self): self.assertRaises(KeyError, self.mapper.remove, self.entity.path, self.metadata) def test_remove_partially_unset_metadata(self): partial_metadata = deepcopy(self.metadata) del partial_metadata["key_1"] entity = self.create_irods_entity(NAMES[0], partial_metadata) self.assertRaises(KeyError, self.mapper.remove, entity.path, self.metadata) def test_remove_subset_of_metadata(self): entity = self.create_irods_entity(NAMES[0], self.metadata) assert len(self.metadata) == 2 partial_metadata_1 = deepcopy(self.metadata) del partial_metadata_1["key_1"] partial_metadata_2 = deepcopy(self.metadata) del partial_metadata_2["key_2"] self.mapper.remove(entity.path, partial_metadata_1) self.assertEqual(self.mapper.get_all(entity.path), partial_metadata_2) def test_remove_all_with_no_paths(self): self.mapper.remove_all([]) def test_remove_all_with_single_path_that_is_invalid(self): self.assertRaises(FileNotFoundError, self.mapper.remove_all, "/invalid") def test_remove_all_with_single_path(self): entity = self.create_irods_entity(NAMES[0], self.metadata) self.mapper.remove_all(entity.path) self.assertEqual(self.mapper.get_all(entity.path), IrodsMetadata()) def test_remove_all_with_multiple_paths_including_an_invalid_path(self): entity = self.create_irods_entity(NAMES[0], self.metadata) self.assertRaises(FileNotFoundError, self.mapper.remove_all, [entity.path, "/invalid"]) def test_remove_all_with_multiple_paths(self): entities = [self.create_irods_entity(name, self.metadata) for name in NAMES] paths = [entity.path for entity in entities] self.mapper.remove_all(paths) self.assertEqual(self.mapper.get_all(paths), [IrodsMetadata() for _ in range(len(entities))])