Repository: iterative/dvc

Issue:
plots: http remote fails to open an existing file
# Bug Report

This thing is a bit of a critical since affects experience with VS Code for new users if we use DVC-tracked plots.

## Description

Run `dvc plots show -v` on a repo with an HTTP remote
Repo should be just cloned, DVC cache is empty
One of the plots should be a DVC-tracked image

Raises: `https://remote.dvc.org/mnist-vscode/97/b176d8fcd0590c82f0f7499850c65b: _request() got an unexpected keyword argument 'encoding'`, full stack trace is below and fails to read the plots.


## Reproduce

Clone https://github.com/iterative/vscode-dvc/tree/42318d2873109061a1f18f37cdcfe8d918bfd48c
Run `dvc plots show -v` in `vscode-dvc/demo`

## Cause

https://github.com/iterative/vscode-dvc/tree/42318d2873109061a1f18f37cdcfe8d918bfd48c

This is probably one of the rare places where we open file as binary via HTTP `fsspec` which is not filtering the `encoding` arg in this case, but `requests` doesn't accept it either - there should be a different way (response encoding or something).

```python    
if extension in (".jpeg", ".jpg", ".gif", ".png"):
        with fs.open(path, "rb") as fd:
            return fd.read()
```

### Environment information

```
DVC version: 2.10.3.dev9+g5067e1f5
---------------------------------
Platform: Python 3.9.12 on macOS-12.3-arm64-arm-64bit
Supports:
	azure (adlfs = 2022.4.0, knack = 0.9.0, azure-identity = 1.10.0),
	gdrive (pydrive2 = 1.10.1),
	gs (gcsfs = 2022.3.0),
	hdfs (fsspec = 2022.3.0, pyarrow = 7.0.0),
	webhdfs (fsspec = 2022.3.0),
	http (aiohttp = 3.8.1, aiohttp-retry = 2.4.6),
	https (aiohttp = 3.8.1, aiohttp-retry = 2.4.6),
	s3 (s3fs = 2022.3.0, boto3 = 1.21.21),
	ssh (sshfs = 2022.3.1),
	oss (ossfs = 2021.8.0),
	webdav (webdav4 = 0.9.7),
	webdavs (webdav4 = 0.9.7)
Cache types: <https://error.dvc.org/no-dvc-cache>
Caches: local
Remotes: https
Workspace directory: apfs on /dev/disk3s1s1
Repo: dvc (subdir), git
```

### Additional information

```python
------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/implementations/http.py", line 383, in _info
    await _file_info(
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/implementations/http.py", line 730, in _file_info
    r = await session.get(url, allow_redirects=ar, **kwargs)
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/aiohttp_retry/client.py", line 98, in __aenter__
    return await self._do_request()
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/aiohttp_retry/client.py", line 86, in _do_request
    raise e
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/aiohttp_retry/client.py", line 71, in _do_request
    response: ClientResponse = await self._request(
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/aiohttp/client.py", line 353, in request
    return _RequestContextManager(self._request(method, url, **kwargs))
TypeError: _request() got an unexpected keyword argument 'encoding'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/ivan/Projects/dvc/dvc/utils/__init__.py", line 497, in wrapper
    vals = func(*args, **kwargs)
  File "/Users/ivan/Projects/dvc/dvc/repo/plots/__init__.py", line 271, in parse
    with fs.open(path, "rb") as fd:
  File "/Users/ivan/Projects/dvc/dvc/fs/base.py", line 185, in open
    return self.fs.open(path, mode=mode, encoding=encoding, **kwargs)
  File "/Users/ivan/Projects/dvc/dvc/fs/repo.py", line 309, in open
    return dvc_fs.open(dvc_path, mode=mode, encoding=encoding, **kwargs)
  File "/Users/ivan/Projects/dvc/dvc/fs/base.py", line 185, in open
    return self.fs.open(path, mode=mode, encoding=encoding, **kwargs)
  File "/Users/ivan/Projects/dvc/dvc/fs/dvc.py", line 78, in open
    return fs.open(fspath, mode=mode, encoding=encoding)
  File "/Users/ivan/Projects/dvc/dvc/fs/base.py", line 185, in open
    return self.fs.open(path, mode=mode, encoding=encoding, **kwargs)
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/spec.py", line 1009, in open
    f = self._open(
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/implementations/http.py", line 343, in _open
    size = size or self.info(path, **kwargs)["size"]
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/asyn.py", line 85, in wrapper
    return sync(self.loop, func, *args, **kwargs)
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/asyn.py", line 65, in sync
    raise return_result
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/asyn.py", line 25, in _runner
    result[0] = await coro
  File "/Users/ivan/Projects/vscode-dvc/demo/.env/lib/python3.9/site-packages/fsspec/implementations/http.py", line 396, in _info
    raise FileNotFoundError(url) from exc
FileNotFoundError: https://remote.dvc.org/mnist-vscode/97/b176d8fcd0590c82f0f7499850c65b
```





Discussion:
`encoding` is None, in this case, we don't really need it
We should not be passing `encoding` outside `kwargs` in our BaseFileSystem as fsspec expects this to be passed via kwargs:

https://github.com/fsspec/filesystem_spec/blob/308600c04176fd74ddcd88d1ea7d5c713b6f558d/fsspec/spec.py#L982-L1012

Resolving patch:
diff --git a/dvc/fs/base.py b/dvc/fs/base.py
--- a/dvc/fs/base.py
+++ b/dvc/fs/base.py
@@ -179,10 +179,11 @@ def open(
         self,
         path: AnyFSPath,
         mode: str = "r",
-        encoding: Optional[str] = None,
         **kwargs,
     ) -> "IO":  # pylint: disable=arguments-differ
-        return self.fs.open(path, mode=mode, encoding=encoding, **kwargs)
+        if "b" in mode:
+            kwargs.pop("encoding", None)
+        return self.fs.open(path, mode=mode, **kwargs)
 
     def cat(
         self,


Test patch: