Do not 'legalize' paths by removing everything following a dot

TIL that `with_suffix` does not simply append the suffix to the filename
- it instead replaces the old/current suffix. Or whatever seems to
look like a suffix, in our case, unfortunately...
This commit is contained in:
Šarūnas Nejus 2025-05-11 01:35:47 +01:00
parent 677204238c
commit de09c3217a
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
3 changed files with 17 additions and 8 deletions

View file

@ -715,7 +715,7 @@ def truncate_path(str_path: str) -> str:
path = Path(str_path)
parent_parts = [truncate_str(p, max_length) for p in path.parts[:-1]]
stem = truncate_str(path.stem, max_length - len(path.suffix))
return str(Path(*parent_parts, stem).with_suffix(path.suffix))
return str(Path(*parent_parts, stem)) + path.suffix
def _legalize_stage(

View file

@ -10,6 +10,11 @@ New features:
Bug fixes:
* :doc:`/reference/pathformat`: Fixed a regression where path legalization
incorrectly removed parts of user-configured path formats that followed a dot
(**.**).
:bug:`5771`
For packagers:
Other changes:

View file

@ -171,6 +171,8 @@ class PathConversionTest(BeetsTestCase):
class TestPathLegalization:
_p = pytest.param
@pytest.fixture(autouse=True)
def _patch_max_filename_length(self, monkeypatch):
monkeypatch.setattr("beets.util.get_max_filename_length", lambda: 5)
@ -178,20 +180,22 @@ class TestPathLegalization:
@pytest.mark.parametrize(
"path, expected",
[
("abcdeX/fgh", "abcde/fgh"),
("abcde/fXX.ext", "abcde/f.ext"),
("a🎹/a.ext", "a🎹/a.ext"),
("ab🎹/a.ext", "ab/a.ext"),
_p("abcdeX/fgh", "abcde/fgh", id="truncate-parent-dir"),
_p("abcde/fXX.ext", "abcde/f.ext", id="truncate-filename"),
# note that 🎹 is 4 bytes long:
# >>> "🎹".encode("utf-8")
# b'\xf0\x9f\x8e\xb9'
_p("a🎹/a.ext", "a🎹/a.ext", id="unicode-fit"),
_p("ab🎹/a.ext", "ab/a.ext", id="unicode-truncate-fully-one-byte-over-limit"),
_p("f.a.e", "f.a.e", id="persist-dot-in-filename"), # see #5771
],
)
) # fmt: skip
def test_truncate(self, path, expected):
path = path.replace("/", os.path.sep)
expected = expected.replace("/", os.path.sep)
assert util.truncate_path(path) == expected
_p = pytest.param
@pytest.mark.parametrize(
"replacements, expected_path, expected_truncated",
[ # [ repl before truncation, repl after truncation ]