Repository: fsspec/filesystem_spec

Issue:
fs.ls("/") raises error after fs.rm("/", recursive=True) for memory filesystem
To replicate this error, run this:

```python
import fsspec

fs = fsspec.filesystem("memory")
fs.rm("/", recursive=True)
fs.ls("/")
```

Which results in the following traceback:

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../site-packages/fsspec/implementations/memory.py", line 91, in ls
    raise FileNotFoundError(path)
FileNotFoundError
```
I would expect it to return an empty list as it does before the `ls.rm()` call.


Discussion:

Patch:
diff --git a/fsspec/implementations/memory.py b/fsspec/implementations/memory.py
index 334f9db..9356a56 100644
--- a/fsspec/implementations/memory.py
+++ b/fsspec/implementations/memory.py
@@ -116,6 +116,9 @@ class MemoryFileSystem(AbstractFileSystem):
 
     def rmdir(self, path):
         path = self._strip_protocol(path)
+        if path == "":
+            # silently avoid deleting FS root
+            return
         if path in self.pseudo_dirs:
             if not self.ls(path):
                 self.pseudo_dirs.remove(path)
@@ -124,7 +127,7 @@ class MemoryFileSystem(AbstractFileSystem):
         else:
             raise FileNotFoundError(path)
 
-    def exists(self, path):
+    def exists(self, path, **kwargs):
         path = self._strip_protocol(path)
         return path in self.store or path in self.pseudo_dirs
 


Test patch:
diff --git a/fsspec/conftest.py b/fsspec/conftest.py
index 393e4c4..47b49c9 100644
--- a/fsspec/conftest.py
+++ b/fsspec/conftest.py
@@ -17,7 +17,7 @@ def m():
     """
     m = fsspec.filesystem("memory")
     m.store.clear()
-    m.pseudo_dirs.clear()
+    m.pseudo_dirs = [""]
     try:
         yield m
     finally:
diff --git a/fsspec/implementations/tests/test_memory.py b/fsspec/implementations/tests/test_memory.py
index 184c9ee..c647fac 100644
--- a/fsspec/implementations/tests/test_memory.py
+++ b/fsspec/implementations/tests/test_memory.py
@@ -150,3 +150,9 @@ def test_seekable(m):
     f.seek(1)
     assert f.read(1) == "a"
     assert f.tell() == 2
+
+
+def test_remove_all(m):
+    m.touch("afile")
+    m.rm("/", recursive=True)
+    assert not m.ls("/")