Skip to content

Commit a8b133d

Browse files
authored
Fix error behavior for the hardlink_to backport and symlink_to for upath.extensions (#508)
* upath: small fixes for hardlink_to backports * tests: update symlink and hardlink tests * tests: lchmod might not be available * tests: better check for lchmod test * tests: adjust lchmod * tests: lchmod raises notimplemented on linux
1 parent d9e80ff commit a8b133d

3 files changed

Lines changed: 31 additions & 1 deletion

File tree

upath/extensions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from urllib.parse import SplitResult
1717

1818
from fsspec import AbstractFileSystem
19+
from pathlib_abc import vfspath
1920

2021
from upath._chain import Chain
2122
from upath._chain import ChainSegment
@@ -160,6 +161,8 @@ def symlink_to(
160161
target: ReadablePathLike,
161162
target_is_directory: bool = False,
162163
) -> None:
164+
if not isinstance(target, str):
165+
target = vfspath(target)
163166
self.__wrapped__.symlink_to(target, target_is_directory=target_is_directory)
164167

165168
def mkdir(
@@ -431,6 +434,8 @@ def is_relative_to(self, other, /, *_deprecated) -> bool: # type: ignore[overri
431434
return self.__wrapped__.is_relative_to(other, *_deprecated)
432435

433436
def hardlink_to(self, target: ReadablePathLike) -> None:
437+
if not isinstance(target, str):
438+
target = vfspath(target)
434439
return self.__wrapped__.hardlink_to(target)
435440

436441
def match(self, pattern: str, *, case_sensitive: bool | None = None) -> bool:

upath/implementations/local.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ def relative_to( # type: ignore[override]
642642

643643
def hardlink_to(self, target: ReadablePathLike) -> None:
644644
try:
645-
os.link(target, self) # type: ignore[arg-type]
645+
os.link(os.fspath(target), os.fspath(self)) # type: ignore[arg-type]
646646
except AttributeError:
647647
raise UnsupportedOperation("hardlink operation not supported")
648648

upath/tests/test_extensions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import sys
3+
from contextlib import nullcontext
34

45
import pytest
56

@@ -130,6 +131,30 @@ def test_cwd(self):
130131
with pytest.raises(UnsupportedOperation):
131132
type(self.path).cwd()
132133

134+
def test_lchmod(self):
135+
# setup
136+
a = self.path.joinpath("a")
137+
b = self.path.joinpath("b")
138+
a.touch()
139+
b.symlink_to(a)
140+
141+
# see: https://github.com/python/cpython/issues/108660#issuecomment-1854645898
142+
if hasattr(os, "lchmod") or os.chmod in os.supports_follow_symlinks:
143+
cm = nullcontext()
144+
else:
145+
cm = pytest.raises((UnsupportedOperation, NotImplementedError))
146+
with cm:
147+
b.lchmod(mode=0o777)
148+
149+
def test_symlink_to(self):
150+
self.path.joinpath("link").symlink_to(self.path)
151+
152+
def test_hardlink_to(self):
153+
try:
154+
self.path.joinpath("link").hardlink_to(self.path)
155+
except PermissionError:
156+
pass # hardlink may require elevated permissions
157+
133158

134159
def test_custom_subclass():
135160

0 commit comments

Comments
 (0)