{ stdenv , lib , fetchFromGitHub , writeScript , glibcLocales , diffPlugins , substituteAll , pythonPackages # can be null, if you wish to disable a reference to it. It's needed for the # artresizer, see: # https://beets.readthedocs.io/en/v1.6.0/plugins/fetchart.html#image-resizing , imagemagick , gobject-introspection , gst_all_1 , runtimeShell # external plugins package set , beetsExternalPlugins , enableAbsubmit ? lib.elem stdenv.hostPlatform.system essentia-extractor.meta.platforms, essentia-extractor , enableAcousticbrainz ? true , enableAcoustid ? true , enableAura ? true , enableBadfiles ? true, flac, mp3val , enableBeatport ? true , enableBpsync ? true , enableConvert ? true, ffmpeg , enableDeezer ? true , enableDiscogs ? true , enableEmbyupdate ? true , enableFetchart ? true , enableKeyfinder ? true, keyfinder-cli , enableKodiupdate ? true , enableLastfm ? true , enableLoadext ? true , enableLyrics ? true , enableMpd ? true , enablePlaylist ? true , enableReplaygain ? true , enableSonosUpdate ? true , enableSubsonicplaylist ? true , enableSubsonicupdate ? true , enableThumbnails ? true , enableWeb ? true # External plugins , enableAlternatives ? false , enableCopyArtifacts ? false , enableExtraFiles ? false , bashInteractive, bash-completion }: assert enableBpsync -> enableBeatport; let optionalPlugins = { absubmit = enableAbsubmit; acousticbrainz = enableAcousticbrainz; aura = enableAura; badfiles = enableBadfiles; beatport = enableBeatport; bpsync = enableBpsync; chroma = enableAcoustid; convert = enableConvert; deezer = enableDeezer; discogs = enableDiscogs; embyupdate = enableEmbyupdate; fetchart = enableFetchart; keyfinder = enableKeyfinder; kodiupdate = enableKodiupdate; lastgenre = enableLastfm; lastimport = enableLastfm; loadext = enableLoadext; lyrics = enableLyrics; mpdstats = enableMpd; mpdupdate = enableMpd; playlist = enablePlaylist; replaygain = enableReplaygain; sonosupdate = enableSonosUpdate; subsonicplaylist = enableSubsonicplaylist; subsonicupdate = enableSubsonicupdate; thumbnails = enableThumbnails; web = enableWeb; }; pluginsWithoutDeps = [ "albumtypes" "bareasc" "bench" "bpd" "bpm" "bucket" "duplicates" "edit" "embedart" "export" "filefilter" "fish" "freedesktop" "fromfilename" "ftintitle" "fuzzy" "hook" "ihate" "importadded" "importfeeds" "info" "inline" "ipfs" "gmusic" "mbcollection" "mbsubmit" "mbsync" "metasync" "missing" "parentwork" "permissions" "play" "plexupdate" "random" "rewrite" "scrub" "smartplaylist" "spotify" "the" "types" "unimported" "zero" ]; enabledOptionalPlugins = lib.attrNames (lib.filterAttrs (_: lib.id) optionalPlugins); allPlugins = pluginsWithoutDeps ++ lib.attrNames optionalPlugins; allEnabledPlugins = pluginsWithoutDeps ++ enabledOptionalPlugins; testShell = "${bashInteractive}/bin/bash --norc"; completion = "${bash-completion}/share/bash-completion/bash_completion"; in pythonPackages.buildPythonApplication rec { pname = "beets"; version = "1.6.0"; src = fetchFromGitHub { owner = "beetbox"; repo = "beets"; rev = "v${version}"; sha256 = "sha256-fT+rCJJQR7bdfAcmeFRaknmh4ZOP4RCx8MXpq7/D8tM="; }; propagatedBuildInputs = [ pythonPackages.six pythonPackages.enum34 pythonPackages.jellyfish pythonPackages.munkres pythonPackages.musicbrainzngs pythonPackages.mutagen pythonPackages.pyyaml pythonPackages.unidecode pythonPackages.gst-python pythonPackages.pygobject3 pythonPackages.reflink pythonPackages.confuse pythonPackages.mediafile gobject-introspection ] ++ lib.optional enableAbsubmit essentia-extractor ++ lib.optional enableAcoustid pythonPackages.pyacoustid ++ lib.optional enableBeatport pythonPackages.requests-oauthlib ++ lib.optional enableConvert ffmpeg ++ lib.optional enableDiscogs pythonPackages.discogs-client ++ lib.optional (enableFetchart || enableDeezer || enableEmbyupdate || enableKodiupdate || enableLoadext || enablePlaylist || enableSubsonicplaylist || enableSubsonicupdate || enableAcousticbrainz) pythonPackages.requests ++ lib.optional enableKeyfinder keyfinder-cli ++ lib.optional enableLastfm pythonPackages.pylast ++ lib.optional enableLyrics pythonPackages.beautifulsoup4 ++ lib.optional enableMpd pythonPackages.mpd2 ++ lib.optional enableSonosUpdate pythonPackages.soco ++ lib.optional enableThumbnails pythonPackages.pyxdg ++ lib.optional (enableAura || enableWeb) pythonPackages.flask ++ lib.optional enableAlternatives beetsExternalPlugins.alternatives ++ lib.optional enableCopyArtifacts beetsExternalPlugins.copyartifacts ++ lib.optional enableExtraFiles beetsExternalPlugins.extrafiles ; buildInputs = [ ] ++ (with gst_all_1; [ gst-plugins-base gst-plugins-good gst-plugins-ugly ]); checkInputs = with pythonPackages; [ beautifulsoup4 mock nose rarfile responses # Although considered as plugin dependencies, they are needed for the # tests, for disabling them via an override makes the build fail. see: # https://github.com/beetbox/beets/blob/v1.6.0/setup.py pylast mpd2 discogs-client pyxdg ]; patches = [ # Bash completion fix for Nix ./bash-completion-always-print.patch ] # Fix path to imagemagick, used for the artresizer.py file. This reference # to imagemagick might be expensive for some people, so the patch can be # disabled if imagemagick is set to null ++ lib.optional (imagemagick != null) (substituteAll { src = ./imagemagick-nix-path.patch; inherit imagemagick; }) # We need to force ffmpeg as the default, since we do not package # bs1770gain, and set the absolute path there, to avoid impurities. ++ lib.optional enableReplaygain (substituteAll { src = ./replaygain-default-ffmpeg.patch; ffmpeg = lib.getBin ffmpeg; }) # Put absolute Nix paths in place ++ lib.optional enableConvert (substituteAll { src = ./convert-plugin-ffmpeg-path.patch; ffmpeg = lib.getBin ffmpeg; }) ++ lib.optional enableBadfiles (substituteAll { src = ./badfiles-plugin-nix-paths.patch; inherit mp3val flac; }) ; # Disable failing tests postPatch = '' echo echo completion tests passed > test/rsrc/test_completion.sh # https://github.com/beetbox/beets/issues/1187 sed -i -e 's/len(mf.images)/0/' test/test_zero.py ''; postInstall = '' mkdir -p $out/share/zsh/site-functions cp extra/_beet $out/share/zsh/site-functions/ ''; doCheck = true; preCheck = '' find beetsplug -mindepth 1 \ \! -path 'beetsplug/__init__.py' -a \ \( -name '*.py' -o -path 'beetsplug/*/__init__.py' \) -print \ | sed -n -re 's|^beetsplug/([^/.]+).*|\1|p' \ | sort -u > plugins_available ${diffPlugins allPlugins "plugins_available"} ''; checkPhase = '' runHook preCheck LANG=en_US.UTF-8 \ LOCALE_ARCHIVE=${assert stdenv.isLinux; glibcLocales}/lib/locale/locale-archive \ BEETS_TEST_SHELL="${testShell}" \ BASH_COMPLETION_SCRIPT="${completion}" \ HOME="$(mktemp -d)" nosetests -v runHook postCheck ''; doInstallCheck = true; installCheckPhase = '' runHook preInstallCheck tmphome="$(mktemp -d)" EDITOR="${writeScript "beetconfig.sh" '' #!${runtimeShell} cat > "$1" <