google / google/etils

_OsPathBackend.copy() raises PermissionError instead of IsADirectoryError on Windows for a directory source

Open Beginner friendly
#818 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
259
Forks
34
Avg merge
57m
Merged PRs (30d)
1

Description

`_OsPathBackend.copy()` has no check for a directory source:

```python
def copy(self, path: PathLike, dst: PathLike, overwrite: bool) -> None:
if not overwrite and self.exists(dst):
raise FileExistsError(f'{dst} already exists. Cannot copy {path}.')
shutil.copyfile(path, dst)
```

Its sibling `_FileSystemSpecBackend.copy()` does, at `backend.py:563-567`:

```python
if self.isdir(path) and not is_dir_dst:
raise IsADirectoryError(f'Cannot copy to {dst}. Path {path} is a directory')
```

On POSIX the missing check does not matter, because `open()` on a directory raises `IsADirectoryError` natively and `shutil.copyfile` propagates it. On Windows, opening a directory is "Access is denied":

```python
# Windows 11, CPython 3.13.13
shutil.copyfile(srcdir, dst)
# PermissionError: [Errno 13] Permission denied: '...\\srcdir'
# isinstance(e, IsADirectoryError) -> False
```

So caller code written against the contract the fsspec backend states, and against the behaviour the os backend shows on Linux, does not catch the Windows exception. `PermissionError` and `IsADirectoryError` are siblings under `OSError`, neither inherits from the other, so an `except IsADirectoryError` clause silently misses it and the error surfaces somewhere unrelated.

`test_backend[_test_copy]` and `test_backend[_test_copy_with_overwrite]` already assert the intended type and report this. Neither has run on Windows, because the module fails collection there on `import grp`.

I have no Linux or macOS machine, so the POSIX half above is read from the documented `open()` behaviour rather than measured.

Contributor guide

Open the contributing guide

Research direction

Start in backend.py at _OsPathBackend.copy() and compare it with _FileSystemSpecBackend.copy() around lines 563-567. Run test_backend[_test_copy] and test_backend[_test_copy_with_overwrite] on Windows, after addressing the import grp collection blocker, and confirm directory sources raise IsADirectoryError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.