Repository: fsspec/universal_pathlib

Issue:
UPath("/", protocol="memory").is_absolute() == False
I can kinda see why this is happening in the code, but can't tell if it's intentional. 

Naively, I'd expect `UPath("/", protocol="memory")` to be an absolute path. Especially since `UPath("/foo", protocol="memory")` **is** an absolute path, and `UPath("/foo", protocol="memory").parent == UPath("/", protocol="memory")`.

I'd guess this is a bug, but wasn't sure if this was a side-effect of trying to generalise everything consistently, especially with regard to the `memory` filesystem. 

Similarly, `UPath(".").name == ""` which makes sense to me, but `UPath(".", protocol="memory").name == '.'` . Was this an intentional decision or is it a bug?

Thanks in advance!

Discussion:

Fix (patch):
diff --git a/upath/implementations/memory.py b/upath/implementations/memory.py
index 052ed3bc..a912645b 100644
--- a/upath/implementations/memory.py
+++ b/upath/implementations/memory.py
@@ -44,7 +44,12 @@ def iterdir(self) -> Iterator[Self]:
     @property
     def path(self) -> str:
         path = super().path
-        return "/" if path == "." else path
+        return "/" if path in {"", "."} else path
+
+    def is_absolute(self) -> bool:
+        if self._relative_base is None and self.__vfspath__() == "/":
+            return True
+        return super().is_absolute()
 
     def __str__(self) -> str:
         s = super().__str__()


Test changes:
diff --git a/upath/tests/cases.py b/upath/tests/cases.py
index 08557fe2..f93e1dd0 100644
--- a/upath/tests/cases.py
+++ b/upath/tests/cases.py
@@ -782,3 +782,9 @@ def test_trailing_slash_is_stripped(self):
         else:
             assert not self.path.joinpath("key").path.endswith("/")
             assert not self.path.joinpath("key/").path.endswith("/")
+
+    def test_parents_are_absolute(self):
+        # this is a cross implementation compatible way to ensure that
+        # the path representing the root is absolute
+        is_absolute = [p.is_absolute() for p in self.path.parents]
+        assert all(is_absolute)
diff --git a/upath/tests/implementations/test_data.py b/upath/tests/implementations/test_data.py
index 1d55c471..248fb5c5 100644
--- a/upath/tests/implementations/test_data.py
+++ b/upath/tests/implementations/test_data.py
@@ -300,3 +300,7 @@ def test_trailing_slash_joinpath_is_identical(self):
     @pytest.mark.skip(reason="DataPath does not support joins")
     def test_trailing_slash_is_stripped(self):
         pass
+
+    @pytest.mark.skip(reason="DataPath does not support joins")
+    def test_parents_are_absolute(self):
+        pass
diff --git a/upath/tests/test_core.py b/upath/tests/test_core.py
index bc145432..7864cf3f 100644
--- a/upath/tests/test_core.py
+++ b/upath/tests/test_core.py
@@ -79,6 +79,13 @@ def test_iterdir_no_dir(self):
         # so this test would need to have an iterdir fix.
         super().test_iterdir_no_dir()
 
+    @pytest.mark.skipif(
+        sys.platform.startswith("win"),
+        reason="mock fs is not well defined on windows",
+    )
+    def test_parents_are_absolute(self):
+        return super().test_parents_are_absolute()
+
 
 def test_multiple_backend_paths(local_testdir):
     path = "s3://bucket/"