Repository: wright-group/WrightTools

Issue:
api for renaming group
need api to cleanly rename objects derived from `Group` (`Collection` and `Data`)

we need to be careful because renaming a `Group` implies changing the `fullpath` of all objects that it contains---this is annoying because of the way we use the `instances` class attribute


Discussion:

Resolving patch:
diff --git a/WrightTools/_dataset.py b/WrightTools/_dataset.py
--- a/WrightTools/_dataset.py
+++ b/WrightTools/_dataset.py
@@ -4,7 +4,6 @@
 # --- import --------------------------------------------------------------------------------------
 
 
-import posixpath
 import collections
 
 import numpy as np
@@ -87,8 +86,7 @@ def __init__(self, *args, **kwargs):
     def __new__(cls, parent, id, **kwargs):
         """New object formation handler."""
         fullpath = parent.fullpath + h5py.h5i.get_name(id).decode()
-        if fullpath.startswith("//"):
-            fullpath = fullpath[1:]
+        fullpath = fullpath.replace("//", "/")
         if fullpath in cls._instances.keys():
             return cls._instances[fullpath]
         else:
@@ -135,7 +133,7 @@ def full(self):
     @property
     def fullpath(self):
         """Full path: file and internal structure."""
-        return self.parent.fullpath + posixpath.sep + self.natural_name
+        return self.parent.filepath + "::" + self.name
 
     @property
     def natural_name(self):
diff --git a/WrightTools/_group.py b/WrightTools/_group.py
--- a/WrightTools/_group.py
+++ b/WrightTools/_group.py
@@ -17,6 +17,7 @@
 
 import h5py
 
+from ._dataset import Dataset
 from . import kit as wt_kit
 from . import exceptions as wt_exceptions
 from . import __wt5_version__
@@ -223,6 +224,16 @@ def natural_name(self, value):
         """Set natural name."""
         if value is None:
             value = ""
+        if hasattr(self, "_natural_name") and self.name != "/":
+            keys = [k for k in self._instances.keys() if k.startswith(self.fullpath)]
+            dskeys = [k for k in Dataset._instances.keys() if k.startswith(self.fullpath)]
+            self.parent.move(self._natural_name, value)
+            for k in keys:
+                obj = self._instances.pop(k)
+                self._instances[obj.fullpath] = obj
+            for k in dskeys:
+                obj = Dataset._instances.pop(k)
+                Dataset._instances[obj.fullpath] = obj
         self._natural_name = self.attrs["name"] = value
 
     @property


Test patch:
diff --git a/tests/base.py b/tests/base.py
--- a/tests/base.py
+++ b/tests/base.py
@@ -16,12 +16,22 @@ def test_named_root_collection():
     c = wt.Collection(name="blaise")
     assert c.natural_name == "blaise"
     assert c.attrs["name"] == "blaise"
+    assert c.name == "/"
+    c.natural_name = "kyle"
+    assert c.natural_name == "kyle"
+    assert c.attrs["name"] == "kyle"
+    assert c.name == "/"
 
 
 def test_named_root_data():
     d = wt.Data(name="blaise")
     assert d.natural_name == "blaise"
     assert d.attrs["name"] == "blaise"
+    assert d.name == "/"
+    d.natural_name = "kyle"
+    assert d.natural_name == "kyle"
+    assert d.attrs["name"] == "kyle"
+    assert d.name == "/"
 
 
 def test_parent_child():
@@ -34,6 +44,9 @@ def test_parent_child():
     assert grandchild.fullpath in wt._group.Group._instances.keys()
     assert child.fullpath in wt._group.Group._instances.keys()
     assert parent.fullpath in wt._group.Group._instances.keys()
+    child.natural_name = "duck"
+    assert grandchild.fullpath.endswith("/duck/hen")
+    assert grandchild.fullpath in wt._group.Group._instances.keys()
 
 
 def test_single_instance_collection():