diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index be258a463..744d8040d 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -6,6 +6,8 @@ Dev Fixes +- Accept full FTP URLs in direct ``cat_file`` and ``get_file`` calls. + - Strip the protocol from the path in ``LocalFileSystem.chmod``. - Forward the wrapped filesystem's ``local_file`` flag through ``DirFileSystem`` (#1110). diff --git a/fsspec/implementations/ftp.py b/fsspec/implementations/ftp.py index ada1d0ed9..e2d2dd46c 100644 --- a/fsspec/implementations/ftp.py +++ b/fsspec/implementations/ftp.py @@ -195,6 +195,7 @@ def info(self, path, **kwargs): return out def get_file(self, rpath, lpath, **kwargs): + rpath = self._strip_protocol(rpath) if self.isdir(rpath): if not os.path.exists(lpath): os.mkdir(lpath) @@ -216,6 +217,7 @@ def cb(x): outfile.close() def cat_file(self, path, start=None, end=None, **kwargs): + path = self._strip_protocol(path) if end is not None or (start is not None and start < 0): return super().cat_file(path, start, end, **kwargs) out = [] diff --git a/fsspec/implementations/tests/test_ftp.py b/fsspec/implementations/tests/test_ftp.py index 3b892fc31..c8bbd264a 100644 --- a/fsspec/implementations/tests/test_ftp.py +++ b/fsspec/implementations/tests/test_ftp.py @@ -217,6 +217,27 @@ def test_cat_get(ftp_writable, tmpdir): assert open(fn, "rb").read() == data +@pytest.mark.parametrize("start,end", [(None, None), (3, None), (-3, None), (2, 8)]) +def test_cat_file_with_protocol(ftp_writable, start, end): + host, port, user, pw = ftp_writable + fs = FTPFileSystem(host, port, user, pw) + data = b"0123456789" + fs.pipe("/url-file", data) + url = f"ftp://{host}:{port}/url-file" + assert fs.cat_file(url, start=start, end=end) == data[start:end] + + +@pytest.mark.parametrize("file_like", [False, True]) +def test_get_file_with_protocol(ftp_writable, tmp_path, file_like): + host, port, user, pw = ftp_writable + fs = FTPFileSystem(host, port, user, pw) + data = b"download through an FTP URL" + fs.pipe("/url-file", data) + target = io.BytesIO() if file_like else tmp_path / "download" + fs.get_file(f"ftp://{host}:{port}/url-file", target) + assert (target.getvalue() if file_like else target.read_bytes()) == data + + @pytest.mark.parametrize("start", [-3, -10, -100, 0, 3, None]) def test_cat_file_start(ftp_writable, start): host, port, user, pw = ftp_writable