Skip to content

Commit

Permalink
microopt: reorder to remove assertions, lazy imports (#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
skshetry authored Dec 6, 2023
1 parent 4e1efe1 commit 3346a01
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 38 deletions.
55 changes: 21 additions & 34 deletions src/dvc_objects/fs/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
import errno
import logging
import os
import platform
import stat
import sys
import functools
from typing import TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -34,7 +32,6 @@ def symlink(source: "AnyFSPath", link_name: "AnyFSPath") -> None:
os.symlink(source, link_name)


@functools.lru_cache(maxsize=1)
def _clonefile():
def _cdll(name):
return ctypes.CDLL(name, use_errno=True)
Expand Down Expand Up @@ -68,53 +65,43 @@ def _cdll(name):
return clonefile


def _reflink_darwin(src: "AnyFSPath", dst: "AnyFSPath") -> None:
# NOTE: reflink may (macos) or may not (linux) clone permissions,
# so the user needs to handle those himself.
if sys.platform == "darwin":
clonefile = _clonefile()

ret = clonefile(
ctypes.c_char_p(os.fsencode(src)),
ctypes.c_char_p(os.fsencode(dst)),
ctypes.c_int(0),
)
if ret:
err = ctypes.get_errno()
msg = os.strerror(err)
raise OSError(err, msg)

def reflink(src, dst):
ret = clonefile(
ctypes.c_char_p(os.fsencode(src)),
ctypes.c_char_p(os.fsencode(dst)),
ctypes.c_int(0),
)
if ret:
err = ctypes.get_errno()
msg = os.strerror(err)
raise OSError(err, msg)

def _reflink_linux(src: "AnyFSPath", dst: "AnyFSPath") -> None:
elif sys.platform == "linux":
import fcntl # pylint: disable=import-error
from contextlib import suppress

FICLONE = 0x40049409

if sys.platform != "linux":
raise AssertionError
else:
def reflink(src, dst):
try:
with open(src, "rb") as s, open(dst, "wb+") as d:
fcntl.ioctl(d.fileno(), FICLONE, s.fileno())
except OSError:
with suppress(OSError):
try:
os.unlink(dst)
except OSError:
pass
raise
else:


def reflink(source: "AnyFSPath", link_name: "AnyFSPath") -> None:
source, link_name = os.fspath(source), os.fspath(link_name)

# NOTE: reflink may (macos) or may not (linux) clone permissions,
# so the user needs to handle those himself.

system = platform.system()
if system == "Darwin":
_reflink_darwin(source, link_name)
elif system == "Linux":
_reflink_linux(source, link_name)
else:
def reflink(src, dst):
raise OSError(
errno.ENOTSUP,
f"reflink is not supported on '{system}'",
f"reflink is not supported on '{sys.platform}'",
)


Expand Down
9 changes: 6 additions & 3 deletions tests/benchmarks/test_fs.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import errno
import pytest
import shutil

import pytest
from reflink import reflink as pyreflink
from reflink.error import ReflinkImpossibleError
from dvc_objects.fs.system import reflink, hardlink, symlink

from dvc_objects.fs.system import hardlink, reflink, symlink

NLINKS = 10000


@pytest.mark.parametrize(
"link", [pytest.param(pyreflink, id="pyreflink"), reflink, hardlink, symlink]
"link",
[pytest.param(pyreflink, id="pyreflink"), reflink, hardlink, symlink],
)
def test_link(benchmark, tmp_path, link):
(tmp_path / "original").mkdir()
Expand Down
3 changes: 2 additions & 1 deletion tests/test_reflink.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import errno
import os
import stat
from os import fspath, umask
from pathlib import Path
Expand Down Expand Up @@ -37,12 +38,12 @@ def test_reflink(test_dir):
assert stat_mode == (0o666 & ~umask(0))


@pytest.mark.skipif(os.name != "nt", reason="only run in Windows")
def test_reflink_unsupported_on_windows(test_dir, mocker):
src = test_dir / "source"
dest = test_dir / "dest"
src.write_bytes(b"content")

mocker.patch("platform.system", mocker.MagicMock(return_value="Windows"))
with pytest.raises(OSError) as exc:
reflink(fspath(src), fspath(dest))

Expand Down

0 comments on commit 3346a01

Please sign in to comment.