Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies and do not install reflink on Windows for tests #5407

Merged
merged 6 commits into from
Sep 8, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
run: |
sudo apt update
sudo apt install ffmpeg gobject-introspection libgirepository1.0-dev
poetry install --extras replaygain
poetry install --extras=replaygain --extras=reflink

- name: Install Python dependencies
run: poetry install --only=main,test --extras=autobpm
Expand Down
8 changes: 0 additions & 8 deletions beets/test/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import os
import sys
import tempfile
import unittest
from contextlib import contextmanager

Expand Down Expand Up @@ -66,13 +65,6 @@
HAVE_SYMLINK = sys.platform != "win32"
HAVE_HARDLINK = sys.platform != "win32"

try:
import reflink

HAVE_REFLINK = reflink.supported_at(tempfile.gettempdir())
except ImportError:
HAVE_REFLINK = False


def item(lib=None):
global _item_ident
Expand Down
16 changes: 15 additions & 1 deletion beets/test/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from functools import cached_property
from io import StringIO
from pathlib import Path
from tempfile import mkdtemp, mkstemp
from tempfile import gettempdir, mkdtemp, mkstemp
from typing import Any, ClassVar
from unittest.mock import patch

Expand Down Expand Up @@ -147,6 +147,20 @@ def has_program(cmd, args=["--version"]):
return True


def check_reflink_support(path: str) -> bool:
try:
import reflink
except ImportError:
return False

return reflink.supported_at(path)


NEEDS_REFLINK = unittest.skipUnless(
check_reflink_support(gettempdir()), "no reflink support for libdir"
)


class TestHelper(_common.Assertions):
"""Helper mixin for high-level cli and plugin tests.

Expand Down
40 changes: 22 additions & 18 deletions beets/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# included in all copies or substantial portions of the Software.

"""Miscellaneous utility functions."""

from __future__ import annotations

import errno
Expand All @@ -29,6 +30,7 @@
from collections import Counter
from contextlib import suppress
from enum import Enum
from importlib import import_module
from logging import Logger
from multiprocessing.pool import ThreadPool
from pathlib import Path
Expand Down Expand Up @@ -166,7 +168,7 @@
"""Provide the canonical form of the path suitable for storing in
the database.
"""
path = syspath(path, prefix=False)

Check failure on line 171 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Incompatible types in assignment (expression has type "str", variable has type "bytes")
path = os.path.normpath(os.path.abspath(os.path.expanduser(path)))
return bytestring_path(path)

Expand All @@ -180,7 +182,7 @@

The argument should *not* be the result of a call to `syspath`.
"""
out = []

Check failure on line 185 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Need type annotation for "out" (hint: "out: List[<type>] = ...")
last_path = None
while path:
path = os.path.dirname(path)
Expand All @@ -197,17 +199,17 @@

def sorted_walk(
path: AnyStr,
ignore: Sequence = (),

Check failure on line 202 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Missing type parameters for generic type "Sequence"
ignore_hidden: bool = False,
logger: Optional[Logger] = None,
) -> Generator[Tuple, None, None]:

Check failure on line 205 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Missing type parameters for generic type "Tuple"
"""Like `os.walk`, but yields things in case-insensitive sorted,
breadth-first order. Directory and file names matching any glob
pattern in `ignore` are skipped. If `logger` is provided, then
warning messages are logged there when a directory cannot be listed.
"""
# Make sure the paths aren't Unicode strings.
path = bytestring_path(path)

Check failure on line 212 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Incompatible types in assignment (expression has type "bytes", variable has type "str")
ignore = [bytestring_path(i) for i in ignore]

# Get all the directories and files at this level.
Expand All @@ -224,7 +226,7 @@
dirs = []
files = []
for base in contents:
base = bytestring_path(base)

Check failure on line 229 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Incompatible types in assignment (expression has type "bytes", variable has type "str")

# Skip ignored filenames.
skip = False
Expand All @@ -240,8 +242,8 @@
continue

# Add to output as either a file or a directory.
cur = os.path.join(path, base)

Check failure on line 245 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

No overload variant of "join" matches argument types "bytes", "str"
if (ignore_hidden and not hidden.is_hidden(cur)) or not ignore_hidden:

Check failure on line 246 in beets/util/__init__.py

View workflow job for this annotation

GitHub Actions / Check types with mypy

Argument 1 to "is_hidden" has incompatible type "str"; expected "Union[bytes, Path]"
if os.path.isdir(syspath(cur)):
dirs.append(base)
else:
Expand Down Expand Up @@ -615,31 +617,33 @@
Raise an `OSError` if `dest` already exists, unless `replace` is
True. If `path` == `dest`, then do nothing.

If reflinking fails and `fallback` is enabled, try copying the file
instead. Otherwise, raise an error without trying a plain copy.

May raise an `ImportError` if the `reflink` module is not available.
If `fallback` is enabled, ignore errors and copy the file instead.
Otherwise, errors are re-raised as FilesystemError with an explanation.
"""
import reflink as pyreflink

if samefile(path, dest):
return

if os.path.exists(syspath(dest)) and not replace:
raise FilesystemError("file exists", "rename", (path, dest))
raise FilesystemError("target exists", "rename", (path, dest))

if fallback:
with suppress(Exception):
return import_module("reflink").reflink(path, dest)
return copy(path, dest, replace)

try:
pyreflink.reflink(path, dest)
except (NotImplementedError, pyreflink.ReflinkImpossibleError):
if fallback:
copy(path, dest, replace)
else:
raise FilesystemError(
"OS/filesystem does not support reflinks.",
"link",
(path, dest),
traceback.format_exc(),
)
import_module("reflink").reflink(path, dest)
except (ImportError, OSError):
raise
except Exception as exc:
msg = {
"EXDEV": "Cannot reflink across devices",
"EOPNOTSUPP": "Device does not support reflinks",
}.get(str(exc), "OS does not support reflinks")

raise FilesystemError(
msg, "reflink", (path, dest), traceback.format_exc()
) from exc


def unique_path(path: bytes) -> bytes:
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -600,13 +600,13 @@ Defaults to ``no``.

This kind of clone is only available on certain filesystems: for example,
btrfs and APFS. For more details on filesystem support, see the `pyreflink`_
documentation. Note that you need to install ``pyreflink``, either through
documentation. Note that you need to install ``pyreflink``, either through
``python -m pip install beets[reflink]`` or ``python -m pip install reflink``.

The option is ignored if ``move`` is enabled (i.e., beets can move or
copy files but it doesn't make sense to do both).

.. _file clones: https://blogs.oracle.com/otn/save-disk-space-on-linux-by-cloning-files-on-btrfs-and-ocfs2
.. _file clones: https://en.wikipedia.org/wiki/Copy-on-write
.. _pyreflink: https://reflink.readthedocs.io/en/latest/

resume
Expand Down
Loading
Loading