_OsPathBackend.copy() raises PermissionError instead of IsADirectoryError on Windows for a directory source
- 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
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