diff --git a/docker/irods_client/tests/test_meta.py b/docker/irods_client/tests/test_meta.py index baaf439b..c07a6ff5 100644 --- a/docker/irods_client/tests/test_meta.py +++ b/docker/irods_client/tests/test_meta.py @@ -137,6 +137,23 @@ def test_metadata_getitem(item_name, request): meta.clear() +@mark.parametrize("item_name", ["collection", "dataobject"]) +def test_metadata_setitem(item_name, request): + item = request.getfixturevalue(item_name) + meta = MetaData(item) + meta.clear() + + meta.add("some_key", "some_value", "some_units") + meta["some_key"] = ("some_key", "new_value", "new_units") + meta["some_key"] = ("some_key", "new_value") + + with pytest.raises(TypeError): + meta["some_key"] = "new_value" + + with pytest.raises(ValueError): + meta["some_key"] = ("some_key", "new_value") + + @mark.parametrize("item_name", ["collection", "dataobject"]) def test_metadata_rename(item_name, request, session): item = request.getfixturevalue(item_name) diff --git a/ibridges/meta.py b/ibridges/meta.py index 349ed5f6..b38bb707 100644 --- a/ibridges/meta.py +++ b/ibridges/meta.py @@ -111,7 +111,7 @@ def find_all(self, key = ..., value = ..., units = ...): all_items.append(meta_item) return all_items - def __getitem__(self, key: Union[str, Sequence[str]]) -> MetaDataItem: + def __getitem__(self, key: Union[str, Sequence[Union[str, None]]]) -> MetaDataItem: """Access the metadata like a dictionary of tuples. Parameters @@ -142,6 +142,36 @@ def __getitem__(self, key: Union[str, Sequence[str]]) -> MetaDataItem: "units as well, for example: meta[key, value, units].") return all_items[0] + def __setitem__(self, key: Union[str, Sequence[Union[str, None]]], other: Sequence[str]): + """Set metadata items like a dictionary of tuples. + + Parameters + ---------- + key + The key to get the metadata for. + other + Key, value, units to set the metadata item to. Units is optional. + + Raises + ------ + TypeError: + If the other parameter is a string. + ValueError: + If the item already exists. + + Examples + -------- + >>> meta["key"] = ("key", "new_value", "new_units") + >>> meta["key"] = ("new_key", "old_value") + + """ + if isinstance(other, str): + raise TypeError("Cannot set the metadata item to a single string value. " + f"Use meta[{key}].key = \"{other}\" to change only the key " + "for example.") + self[key].update(*other) + + def add(self, key: str, value: str, units: Optional[str] = None): """Add metadata to an item. @@ -389,7 +419,7 @@ def key(self, new_key: str): if new_key == self._prc_meta.name: return new_item_values = [new_key, self._prc_meta.value, self._prc_meta.units] - self._rename(new_item_values) + self.update(*new_item_values) @property def value(self) -> Optional[str]: @@ -401,7 +431,7 @@ def value(self, new_value: Optional[str]): if new_value == self._prc_meta.value: return new_item_values = [self._prc_meta.name, new_value, self._prc_meta.units] - self._rename(new_item_values) + self.update(*new_item_values) @property def units(self) -> Optional[str]: @@ -413,7 +443,7 @@ def units(self, new_units: Optional[str]): if new_units == self._prc_meta.units: return new_item_values = [self._prc_meta.name, self._prc_meta.value, new_units] - self._rename(new_item_values) + self.update(*new_item_values) def __repr__(self) -> str: """Representation of the MetaDataItem.""" @@ -429,7 +459,26 @@ def __iter__(self) -> Iterator[Optional[str]]: yield self.value yield self.units - def _rename(self, new_item_key: Sequence[str]): + def update(self, new_key: str, new_value: str, new_units: Optional[str] = None): + """Update the metadata item changing the key/value/units. + + Parameters + ---------- + new_key: + New key to set the metadata item to. + new_value: + New value to set the metadata item to. + new_units: + New units to set the metadata item to, optional. + + Raises + ------ + ValueError: + If the operation could not be completed because of permission error. + Or if the new to be created item already exists. + + """ + new_item_key = (new_key, new_value, new_units) try: _new_item = self._ibridges_meta[new_item_key] except KeyError: