Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions upath/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from urllib.parse import SplitResult

from fsspec import AbstractFileSystem
from pathlib_abc import vfspath

from upath._chain import Chain
from upath._chain import ChainSegment
Expand Down Expand Up @@ -160,6 +161,8 @@ def symlink_to(
target: ReadablePathLike,
target_is_directory: bool = False,
) -> None:
if not isinstance(target, str):
target = vfspath(target)
self.__wrapped__.symlink_to(target, target_is_directory=target_is_directory)

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

def hardlink_to(self, target: ReadablePathLike) -> None:
if not isinstance(target, str):
target = vfspath(target)
return self.__wrapped__.hardlink_to(target)

def match(self, pattern: str, *, case_sensitive: bool | None = None) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion upath/implementations/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ def relative_to( # type: ignore[override]

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

Expand Down
25 changes: 25 additions & 0 deletions upath/tests/test_extensions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
from contextlib import nullcontext

import pytest

Expand Down Expand Up @@ -130,6 +131,30 @@ def test_cwd(self):
with pytest.raises(UnsupportedOperation):
type(self.path).cwd()

def test_lchmod(self):
# setup
a = self.path.joinpath("a")
b = self.path.joinpath("b")
a.touch()
b.symlink_to(a)

# see: https://github.com/python/cpython/issues/108660#issuecomment-1854645898
if hasattr(os, "lchmod") or os.chmod in os.supports_follow_symlinks:
cm = nullcontext()
else:
cm = pytest.raises((UnsupportedOperation, NotImplementedError))
with cm:
b.lchmod(mode=0o777)

def test_symlink_to(self):
self.path.joinpath("link").symlink_to(self.path)

def test_hardlink_to(self):
try:
self.path.joinpath("link").hardlink_to(self.path)
except PermissionError:
pass # hardlink may require elevated permissions


def test_custom_subclass():

Expand Down