Repository: fsspec/filesystem_spec

Issue:
Comparing an AbstractBufferedFile (or subclass) with some objects might raise an exception
The [`__eq__` method of `AbstractBufferedFile`](https://github.com/fsspec/filesystem_spec/blob/95eb5f94d3230fcfa95052eef6cad1d951431ff5/fsspec/spec.py#L1553) assumes that the `other` element of the comparison has the `.mode` attribute:

https://github.com/fsspec/filesystem_spec/blob/95eb5f94d3230fcfa95052eef6cad1d951431ff5/fsspec/spec.py#L1553

However, this is not always the case. E.g. one could decide to compare with `b""`. This will raise an exception (for `AbstractBufferedFile` and all its subclasses).
This eventually causes the issue described here inveniosoftware/invenio-app-rdm#2097 when used in combination with `ZipStream` that indeed, internally, makes exactly the check `data != b''`.
We already provided a [PR to `zipstream-ng`](https://github.com/pR0Ps/zipstream-ng/pull/15) to avoid to do that check, but I think that one should also not assume here that `.mode` always exists?

E.g., if we only want to compare with objects that have a mode, and `other` does not have a mode, one should just return False (they are different objects).
E.g. replace the line above with
```python
return self.mode == "rb" and hasattr(other, "mode") and other.mode == "rb" and hash(self) == hash(other)
```
Before me or my colleague @liotf make a pull request, can you please let us know if you agree with the change? Thanks!

Discussion:

Patch:
diff --git a/fsspec/spec.py b/fsspec/spec.py
index 9a7e4e8..bcc01f5 100644
--- a/fsspec/spec.py
+++ b/fsspec/spec.py
@@ -1698,7 +1698,12 @@ class AbstractBufferedFile(io.IOBase):
         """Files are equal if they have the same checksum, only in read mode"""
         if self is other:
             return True
-        return self.mode == "rb" and other.mode == "rb" and hash(self) == hash(other)
+        return (
+            isinstance(other, type(self))
+            and self.mode == "rb"
+            and other.mode == "rb"
+            and hash(self) == hash(other)
+        )
 
     def commit(self):
         """Move from temp to final destination"""


Test patch:
diff --git a/fsspec/tests/test_spec.py b/fsspec/tests/test_spec.py
index 31788d8..de23d78 100644
--- a/fsspec/tests/test_spec.py
+++ b/fsspec/tests/test_spec.py
@@ -819,6 +819,10 @@ def test_eq():
     result = fs == 1
     assert result is False
 
+    f = AbstractBufferedFile(fs, "misc/foo.txt", cache_type="bytes")
+    result = f == 1
+    assert result is False
+
 
 def test_pickle_multiple():
     a = DummyTestFS(1)