From e16530252f45202caa20d636ebc7d13e51735dce Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Tue, 4 Aug 2026 23:41:28 +0300 Subject: [PATCH] python3Packages.beets-filetote: 1.3.6 -> 1.3.7 Diff: https://github.com/gtronset/beets-filetote/compare/v1.3.6...v1.3.7 Changelog: https://github.com/gtronset/beets-filetote/blob/v1.3.7/CHANGELOG.md --- .../beets-filetote/beets2.13.patch | 288 ------------------ .../python-modules/beets-filetote/default.nix | 31 +- 2 files changed, 2 insertions(+), 317 deletions(-) delete mode 100644 pkgs/development/python-modules/beets-filetote/beets2.13.patch diff --git a/pkgs/development/python-modules/beets-filetote/beets2.13.patch b/pkgs/development/python-modules/beets-filetote/beets2.13.patch deleted file mode 100644 index e50d361fd40a..000000000000 --- a/pkgs/development/python-modules/beets-filetote/beets2.13.patch +++ /dev/null @@ -1,288 +0,0 @@ -From 834f253240fa334f8a73b717c86231a9684ddd07 Mon Sep 17 00:00:00 2001 -From: Andrew Rogl -Date: Fri, 17 Jul 2026 18:43:23 +1000 -Subject: [PATCH 1/3] Fix for issue #350 - ---- - beetsplug/path_utils.py | 7 ++++++- - tests/unit/test_path_utils.py | 31 +++++++++++++++++++++++++++++++ - 2 files changed, 37 insertions(+), 1 deletion(-) - -diff --git a/beetsplug/path_utils.py b/beetsplug/path_utils.py -index 6fadc55f..bb16dd7e 100644 ---- a/beetsplug/path_utils.py -+++ b/beetsplug/path_utils.py -@@ -51,7 +51,12 @@ def discover_artifacts( - """Walks a directory and returns a list of all non-beets-handled files.""" - artifacts: list[Path] = [] - -- for root, _dirs, files in util.sorted_walk(source_path, ignore=ignore): -+ source_path_for_walk = util.bytestring_path(source_path) -+ ignore_for_walk = [util.bytestring_path(pattern) for pattern in ignore] -+ -+ for root, _dirs, files in util.sorted_walk( -+ source_path_for_walk, ignore=ignore_for_walk -+ ): - for filename in files: - full_path_bytes = root + PATH_SEP_BYTES + filename - -diff --git a/tests/unit/test_path_utils.py b/tests/unit/test_path_utils.py -index 579794f9..46940044 100644 ---- a/tests/unit/test_path_utils.py -+++ b/tests/unit/test_path_utils.py -@@ -39,6 +39,37 @@ def test_is_beets_file_type(self, extension: str, expected: bool) -> None: - types = {"mp3": "MPEG", "flac": "FLAC"} - assert path_utils.is_beets_file_type(extension, types) is expected - -+ def test_discover_artifacts_converts_pathlib_source_to_beets_path( -+ self, monkeypatch: pytest.MonkeyPatch -+ ) -> None: -+ """Test that artifact discovery converts pathlib input before calling -+ beets' walk helper, which expects bytes/str paths. -+ """ -+ seen_paths: list[object] = [] -+ -+ def mock_sorted_walk( -+ path: object, -+ ignore: list[object] | None = None, -+ *_args: object, -+ **_kwargs: object, -+ ) -> Iterator[tuple[bytes, list[bytes], list[bytes]]]: -+ seen_paths.append((path, ignore)) -+ assert not isinstance(path, Path) -+ assert ignore is not None -+ assert all(not isinstance(item, Path) for item in ignore) -+ yield (b"/music/album", [], [b"cover.jpg"]) -+ -+ monkeypatch.setattr(path_utils.util, "sorted_walk", mock_sorted_walk) -+ -+ path_utils.discover_artifacts( -+ Path("/music/album"), -+ ignore=[], -+ beets_file_types={}, -+ ) -+ -+ assert seen_paths -+ assert not isinstance(seen_paths[0][0], Path) -+ - def test_discover_artifacts(self, monkeypatch: pytest.MonkeyPatch) -> None: - """Test artifact discovery and ignoring of beets-handled files. Mock - `sorted_walk` to control the filesystem structure. - -From 3ec73e639b8cd03fcaf55d194e09dfcd30d77de3 Mon Sep 17 00:00:00 2001 -From: Andrew Rogl -Date: Fri, 17 Jul 2026 20:52:18 +1000 -Subject: [PATCH 2/3] More updates to work with latest beets - ---- - beetsplug/filetote.py | 25 +++++++++++++++++++++---- - beetsplug/filetote_dataclasses.py | 3 ++- - 2 files changed, 23 insertions(+), 5 deletions(-) - -diff --git a/beetsplug/filetote.py b/beetsplug/filetote.py -index d70fe7c7..5c6dc607 100644 ---- a/beetsplug/filetote.py -+++ b/beetsplug/filetote.py -@@ -485,6 +485,7 @@ def _get_artifact_destination( - mapping: FiletoteMappingModel, - paired: bool = False, - pattern_category: str | None = None, -+ beets_item: Item | None = None, - ) -> Path: - """Returns a destination path an artifact/file should be moved to. The - artifact filename is unique to ensure files aren't overwritten. This also -@@ -513,7 +514,14 @@ def _get_artifact_destination( - ) - - # Get template functions and evaluate against mapping -- template_functions = DefaultTemplateFunctions().functions() -+ # DefaultTemplateFunctions requires both item and lib -+ if beets_item is None: -+ raise ValueError( -+ "beets_item is required to initialize DefaultTemplateFunctions" -+ ) -+ template_functions = DefaultTemplateFunctions( -+ beets_item, self.filetote_config.session.beets_lib -+ ).functions() - artifact_path = Path( - selected_path_template.substitute(mapping_formatted, template_functions) - + artifact_ext -@@ -614,6 +622,7 @@ def _collect_paired_artifacts( - mapping=self._generate_mapping(beets_item, item_destination_path), - source_path=source_path, - item_dest=item_destination_path, -+ beets_item=beets_item, - ) - ) - -@@ -637,6 +646,7 @@ def _update_multimove_artifacts( - mapping=self._generate_mapping(beets_item, destination), - source_path=artifact_collection.source_path, - item_dest=destination, -+ beets_item=beets_item, - ) - break - -@@ -794,6 +804,7 @@ def _queue_artifacts( - mapping=self._generate_mapping(beets_item, item_destination_path), - source_path=source_path, - item_dest=item_destination_path, -+ beets_item=beets_item, - ) - ) - -@@ -841,6 +852,7 @@ def process_events(self, lib: Library) -> None: - source_path=artifact_collection.source_path, - source_artifacts=artifact_collection.artifacts, - mapping=artifact_collection.mapping, -+ beets_item=artifact_collection.beets_item, - ) - - # Handle all shared artifacts for each source directory -@@ -852,10 +864,12 @@ def process_events(self, lib: Library) -> None: - if not shared_artifacts.artifacts: - continue - -- # Mapping derives from the first Item that found this source path -- album_level_mapping = self._run_state.process_queue[ -+ # Get mapping and item from the first collection -+ album_level_collection = self._run_state.process_queue[ - shared_artifacts.mapping_index -- ].mapping -+ ] -+ album_level_mapping = album_level_collection.mapping -+ album_level_item = album_level_collection.beets_item - - artifacts_to_process = [ - FiletoteArtifact(path=shared_artifact, paired=False) -@@ -866,6 +880,7 @@ def process_events(self, lib: Library) -> None: - source_path=source_path, - source_artifacts=artifacts_to_process, - mapping=album_level_mapping, -+ beets_item=album_level_item, - ) - - def _should_process_artifact( -@@ -932,6 +947,7 @@ def process_artifacts( - source_path: Path, - source_artifacts: list[FiletoteArtifact], - mapping: FiletoteMappingModel, -+ beets_item: Item | None = None, - ) -> None: - """Processes and prepares extra files and artifacts for subsequent - manipulation. -@@ -974,6 +990,7 @@ def process_artifacts( - mapping, - artifact.paired, - pattern_category, -+ beets_item, - ) - - if artifact_source == artifact_dest: -diff --git a/beetsplug/filetote_dataclasses.py b/beetsplug/filetote_dataclasses.py -index 80648f95..c7d36b30 100644 ---- a/beetsplug/filetote_dataclasses.py -+++ b/beetsplug/filetote_dataclasses.py -@@ -17,7 +17,7 @@ - from collections.abc import Callable - from pathlib import Path - -- from beets.library import Library -+ from beets.library import Item, Library - from beets.util import MoveOperation - - from .mapping_model import FiletoteMappingModel -@@ -46,6 +46,7 @@ class FiletoteArtifactCollection: - mapping: FiletoteMappingModel - source_path: Path - item_dest: Path -+ beets_item: Item | None = None - - - @dataclass - -From c9617c91c56bb5e3640c3a08ac11fdd79b0a0f7c Mon Sep 17 00:00:00 2001 -From: Andrew Rogl -Date: Sat, 18 Jul 2026 09:45:51 +1000 -Subject: [PATCH 3/3] All local tests passing, but not elegant solution - ---- - beetsplug/path_utils.py | 2 +- - tests/pytest_beets_plugin/plugin_fixture.py | 22 +++++++++++++++++---- - tests/pytest_beets_plugin/utils.py | 7 ++++++- - 3 files changed, 25 insertions(+), 6 deletions(-) - -diff --git a/beetsplug/path_utils.py b/beetsplug/path_utils.py -index bb16dd7e..88efe35b 100644 ---- a/beetsplug/path_utils.py -+++ b/beetsplug/path_utils.py -@@ -155,7 +155,7 @@ def is_multidisc(path_name: Path) -> bool: - """Checks if a directory name matches the multi-disc pattern by replicating the - beets importer's pattern matching for disc folders. - """ -- path_name_bytes = util.bytestring_path(path_name.name) -+ path_name_bytes = util.displayable_path(path_name.name) - - return any(pat.match(path_name_bytes) for pat in MULTIDISC_PATTERNS) - -diff --git a/tests/pytest_beets_plugin/plugin_fixture.py b/tests/pytest_beets_plugin/plugin_fixture.py -index 04d541b9..44665f7a 100644 ---- a/tests/pytest_beets_plugin/plugin_fixture.py -+++ b/tests/pytest_beets_plugin/plugin_fixture.py -@@ -10,6 +10,7 @@ - - from beets import config, library, plugins, util - from beets.importer import ImportSession -+from beets.ui.commands.modify import ModifyOperation - from mediafile import MediaFile - - from ._item_model import MediaMeta -@@ -450,13 +451,26 @@ def _run_cli_modify( # noqa: PLR0913 - album: str | None = None, - ) -> None: - """Run the `modify` CLI command.""" -- mods = mods or {} -- dels = dels or {} -+ if mods: -+ wrapped_mods = { -+ field: ModifyOperation(operator=None, value=val) -+ for field, val in mods.items() -+ } -+ else: -+ wrapped_mods = {} -+ -+ if dels: -+ wrapped_dels = { -+ field: ModifyOperation(operator=None, value=val) -+ for field, val in dels.items() -+ } -+ else: -+ wrapped_dels = {} - - modify_items( - lib=self.lib, -- mods=mods, -- dels=dels, -+ mods=wrapped_mods, -+ dels=wrapped_dels, - query=query, - write=write, - move=move, -diff --git a/tests/pytest_beets_plugin/utils.py b/tests/pytest_beets_plugin/utils.py -index 476ca033..5182d7e4 100644 ---- a/tests/pytest_beets_plugin/utils.py -+++ b/tests/pytest_beets_plugin/utils.py -@@ -53,7 +53,12 @@ def list_files(self, startpath: Path) -> None: - log.debug("{} does not exist", startpath) - return - -- for root, _dirs, files in util.sorted_walk(startpath): -+ source_path_for_walk = util.bytestring_path(startpath) -+ ignore_for_walk = [util.bytestring_path("")] -+ -+ for root, _dirs, files in util.sorted_walk( -+ source_path_for_walk, ignore_for_walk -+ ): - root_path = Path(util.displayable_path(root)) - - try: diff --git a/pkgs/development/python-modules/beets-filetote/default.nix b/pkgs/development/python-modules/beets-filetote/default.nix index 857a64f92d29..918099a45814 100644 --- a/pkgs/development/python-modules/beets-filetote/default.nix +++ b/pkgs/development/python-modules/beets-filetote/default.nix @@ -1,7 +1,6 @@ { lib, fetchFromGitHub, - fetchpatch, buildPythonPackage, # build-system @@ -22,42 +21,16 @@ buildPythonPackage (finalAttrs: { pname = "beets-filetote"; - version = "1.3.6"; + version = "1.3.7"; pyproject = true; src = fetchFromGitHub { owner = "gtronset"; repo = "beets-filetote"; tag = "v${finalAttrs.version}"; - hash = "sha256-ZrF9Z3Eaem8ZzNJgQoW45MvsNOCoLsd7l/yLQ2pldR0="; + hash = "sha256-W5ZZ30LzZLXSMxBBIEQB03Fh04ovETfacZE5gA4oqVM="; }; - patches = [ - # Fixes a few test failures needed since beets 2.12, see: - # https://github.com/gtronset/beets-filetote/issues/328 - # https://github.com/gtronset/beets-filetote/pull/336 - (fetchpatch { - url = "https://github.com/gtronset/beets-filetote/commit/2684482ebe0cd486512b07621e3904de7faf7dc8.patch"; - # Cause merge conflicts - excludes = [ - # The changes here mainly include ci related changes, and hence can be - # disabled. - "pyproject.toml" - "CHANGELOG.md" - ]; - hash = "sha256-zVVJY4+f8A+GBxiHZL8OzLWUUmX9uY25tUoLCkzEHh8="; - }) - # Fixes test errors with beets 2.13. Upstream PR is - # https://github.com/gtronset/beets-filetote/pull/351 . It is not merged and not even - # commented by upstream, so we vendor it instead. - ./beets2.13.patch - ]; - - # https://github.com/gtronset/beets-filetote/issues/328 - postPatch = '' - substituteInPlace pyproject.toml --replace-fail "uv_build>=0.11.21,<0.12" "uv-build" - ''; - build-system = [ uv-build ];