music-assistant: 2.8.7 -> 2.9.4 (#536704)

This commit is contained in:
Sandro
2026-06-29 15:57:04 +00:00
committed by GitHub
35 changed files with 707 additions and 232 deletions
@@ -107,13 +107,17 @@ in
];
};
services.avahi = lib.mkIf (lib.elem "airplay_receiver" cfg.providers) {
enable = true;
openFirewall = lib.mkIf cfg.openFirewall true;
publish = {
services = {
avahi = lib.mkIf (lib.elem "airplay_receiver" cfg.providers) {
enable = true;
userServices = true;
openFirewall = lib.mkIf cfg.openFirewall true;
publish = {
enable = true;
userServices = true;
};
};
music-assistant.providers = cfg.package.providersBuiltins;
};
systemd.services.music-assistant = {
@@ -167,8 +171,12 @@ in
DevicePolicy = "closed";
LockPersonality = true;
# breaks pyopenssl's cffi calls, used in remote access feature
# not compatible with llvmlite which is required by numba -> librosa
MemoryDenyWriteExecute = false;
ProcSubset = "pid";
# required for torch to properly detect the supported engines
# allows Music-Assistant to warn, if x86_64-v2 cpu features are missing
BindReadOnlyPaths = [ "/proc/cpuinfo" ];
ProcSubset = "all";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
@@ -190,7 +198,7 @@ in
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged @resources"
"~@privileged"
"mbind"
]
++ lib.optionals useYTMusic [
+1 -1
View File
@@ -51,10 +51,10 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
icalendar
jsonpath-ng
lxml
mpd2
psutil
pygobject3
python-dateutil
python-mpd2
requests
requests-file
tzdata
+3 -3
View File
@@ -25,16 +25,16 @@
stdenv.mkDerivation {
pname = "cliairplay";
# see the beginning of configure.ac for the upstream version number
version = "1.1-unstable-2026-03-16";
version = "1.5-unstable-2026-05-03";
src = fetchFromGitHub {
owner = "music-assistant";
repo = "cliairplay";
# we try to closely match the commit used in the last music-assistant release from
# https://github.com/music-assistant/server/tree/stable/music_assistant/providers/airplay/bin
rev = "991c65acc2afa17ffe32e279dbc585b0b7f530f8";
rev = "6aeceb49e4e37d044f09be9369b082fc26bcfa19";
fetchSubmodules = true;
hash = "sha256-m1O4l6gFEGNAyskYcRHcA15cubZnNgkaYjdVThRRX7w=";
hash = "sha256-Z2LzRhtQpuXPK6KibnxCqP0V6CulzkwNVHX1V7AFnDA=";
};
nativeBuildInputs = [
+1 -1
View File
@@ -60,7 +60,7 @@ python313Packages.buildPythonApplication (finalAttrs: {
pygobject3
tidalapi
requests
mpd2
python-mpd2
pypresence
]);
+1 -1
View File
@@ -23,7 +23,7 @@ buildPythonApplication (finalAttrs: {
dependencies = [
colorthief
ffmpeg-python
mpd2
python-mpd2
pillow
pixcat
requests
+1 -1
View File
@@ -42,7 +42,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
dependencies = with python3Packages; [
dbus-python
mpd2
python-mpd2
mutagen
pygobject3
];
@@ -0,0 +1,12 @@
diff --git a/music_assistant/mass.py b/music_assistant/mass.py
index 752f9e0af..9d7b3a521 100644
--- a/music_assistant/mass.py
+++ b/music_assistant/mass.py
@@ -923,6 +923,7 @@ async def _load_providers(self) -> None:
changes_made = False
newly_created_defaults: set[str] = set()
for default_provider, require_mdns in DEFAULT_PROVIDERS:
+ continue
if default_provider in default_providers_setup:
# already processed/setup before, skip
continue
@@ -43,7 +43,7 @@ index 0ac8a70f..5d74e25b 100644
"""Set up the YTMusic provider."""
logging.getLogger("yt_dlp").setLevel(self.logger.level + 10)
- await self._install_packages()
self._cookie = self.config.get_value(CONF_COOKIE)
self._cookie = str(self.config.get_value(CONF_COOKIE))
self._po_token_server_url = (
self.config.get_value(CONF_PO_TOKEN_SERVER_URL) or DEFAULT_PO_TOKEN_SERVER_URL
@@ -1103,8 +1102,6 @@ async def _install_packages(self) -> None:
+2 -2
View File
@@ -8,13 +8,13 @@
buildPythonPackage rec {
pname = "music-assistant-frontend";
version = "2.17.146";
version = "2.17.186";
pyproject = true;
src = fetchPypi {
pname = "music_assistant_frontend";
inherit version;
hash = "sha256-VU2SXL6SLFiKntmJJtCabBOYOeImYFPHYxvMPmnhmEc=";
hash = "sha256-dNGzXDRZuQLRkMY0erjJZE4h26yFP4Fdn9a3K6T0RvM=";
};
build-system = [ setuptools ];
+43 -6
View File
@@ -6,6 +6,7 @@
ffmpeg_7-headless,
nixosTests,
replaceVars,
writableTmpDirAsHomeHook,
providers ? [ ],
}:
@@ -15,16 +16,17 @@ let
music-assistant-frontend = prev.callPackage ./frontend.nix { };
music-assistant-models = final.music-assistant-models.overridePythonAttrs (oldAttrs: {
version = "1.1.115";
version = "1.1.129";
src = oldAttrs.src.override {
hash = "sha256-oEXL0B8JNH4PcltpES375ov7QGs+gtYKlMGr1B7BlKY=";
hash = "sha256-6gVHlFTt/bsj4nUGPS6HDUQ7zczpfos75U6l4Yk9W6k=";
};
});
}
);
providerPackages = (import ./providers.nix).providers;
providersMeta = import ./providers.nix;
providerPackages = providersMeta.providers;
providerNames = lib.attrNames providerPackages;
providerDependencies = lib.concatMap (
provider: (providerPackages.${provider} pythonPackages)
@@ -38,14 +40,14 @@ assert
pythonPackages.buildPythonApplication rec {
pname = "music-assistant";
version = "2.8.7";
version = "2.9.4";
pyproject = true;
src = fetchFromGitHub {
owner = "music-assistant";
repo = "server";
tag = version;
hash = "sha256-m91q/8XYoZ5Azu79fKD0euRCuf29w3vj5cxdFheDsmI=";
hash = "sha256-PiSBghhlxknijRqghkO8wn1CB2XqaJrjrvGNvZUlNbo=";
};
patches = [
@@ -78,9 +80,18 @@ pythonPackages.buildPythonApplication rec {
# ^^^^^^^^^^^^^^^
# E IndexError: tuple index out of range
./fix-webserver-tests-in-sandbox.patch
# As providers must be configured through the nixos module, there is no gain
# if Music Assistant tries to enable some of them without the proper dependencies.
./disable-default-provider.diff
];
postPatch = ''
# Undo Python 3.14 only syntax
substituteInPlace music_assistant/controllers/streams/controller.py \
--replace-fail "except BrokenPipeError, ConnectionResetError, ConnectionError:" "except (BrokenPipeError, ConnectionResetError, ConnectionError):" \
--replace-fail "except BrokenPipeError, ConnectionResetError:" "except (BrokenPipeError, ConnectionResetError):"
substituteInPlace pyproject.toml \
--replace-fail "0.0.0" "${version}" \
--replace-fail "==" ">="
@@ -109,6 +120,7 @@ pythonPackages.buildPythonApplication rec {
"mashumaro"
"orjson"
"xmltodict"
"zeroconf"
];
pythonRemoveDeps = [
@@ -139,6 +151,7 @@ pythonPackages.buildPythonApplication rec {
ifaddr
librosa
mashumaro
modern-colorthief
music-assistant-frontend
music-assistant-models
mutagen
@@ -150,6 +163,8 @@ pythonPackages.buildPythonApplication rec {
pyjwt
python-slugify
shortuuid
torch
torchaudio
unidecode
xmltodict
zeroconf
@@ -174,18 +189,36 @@ pythonPackages.buildPythonApplication rec {
with pythonPackages;
[
pytestCheckHook
writableTmpDirAsHomeHook
]
++ lib.concatAttrValues optional-dependencies
++ (lib.concatMap (provider: providerPackages.${provider} python.pkgs) [
++ (lib.concatMap (provider: providerPackages.${provider} pythonPackages) [
"acoustid_lookup"
"audible"
"dlna"
"fastmcp_server"
"jellyfin"
"mpd"
"msx_bridge"
"opensubsonic"
"sendspin"
"smart_fades"
"snapcast"
"sonic_analysis"
"sonic_similarity"
"tidal"
"wiim"
"ytmusic"
]);
preCheck = ''
export NUMBA_CACHE_DIR=$(mktemp -d)
# required for smart_fades tests
mkdir -p $HOME/.cache/torch/hub/checkpoints/
cp ${pythonPackages.beat-this.passthru.small0Ckpt} $HOME/.cache/torch/hub/checkpoints/beat_this-small0.ckpt
'';
disabledTestPaths = [
# no multicast support in build sandbox:
# "OSError: [Errno 19] No such device"
@@ -193,9 +226,12 @@ pythonPackages.buildPythonApplication rec {
# provider is missing dependencies
"tests/providers/apple_music"
"tests/providers/bandcamp"
"tests/providers/hue_entertainment"
"tests/providers/kion_music"
"tests/providers/nicovideo"
"tests/providers/qqmusic"
"tests/providers/yandex_music"
"tests/providers/yandex_ynison"
"tests/providers/zvuk_music"
# mocking music_assistant.providers.airplay.pairing.AirPlayPairing does not work
"tests/providers/airplay/test_player.py::test_start_pairing__pin_decision"
@@ -210,6 +246,7 @@ pythonPackages.buildPythonApplication rec {
providerPackages
providerNames
;
providersBuiltins = providersMeta.builtins;
tests = nixosTests.music-assistant;
};
+102 -7
View File
@@ -1,8 +1,27 @@
# Do not edit manually, run ./update-providers.py
{
version = "2.8.7";
version = "2.9.4";
builtins = [
"builtin"
"coverartarchive"
"fanarttv"
"itunes_artwork"
"local_audio"
"loudness_analysis"
"lrclib"
"musicbrainz"
"sendspin"
"sync_group"
"theaudiodb"
"universal_player"
"wikipedia"
];
providers = {
acoustid_lookup =
ps: with ps; [
pyacoustid
];
airplay =
ps: with ps; [
srptools
@@ -65,6 +84,10 @@
];
fanarttv = ps: [
];
fastmcp_server =
ps: with ps; [
fastmcp
];
filesystem_local = ps: [
];
filesystem_nfs = ps: [
@@ -89,10 +112,14 @@
ps: with ps; [
pyheos
];
hue_entertainment = ps: [
]; # missing hue-entertainment
ibroadcast = ps: [
]; # missing ibroadcastaio
internet_archive = ps: [
];
itunes_artwork = ps: [
];
itunes_podcasts = ps: [
];
jellyfin =
@@ -101,6 +128,8 @@
];
kion_music = ps: [
]; # missing yandex-music
lastfm_recommendations = ps: [
];
lastfm_scrobble =
ps: with ps; [
pylast
@@ -109,16 +138,40 @@
ps: with ps; [
liblistenbrainz
];
local_audio =
ps: with ps; [
sounddevice
];
loudness_analysis = ps: [
];
lrclib = ps: [
];
motherearthradio = ps: [
];
mpd =
ps: with ps; [
python-mpd2
];
msx_bridge =
ps: with ps; [
pydantic
];
musicbrainz = ps: [
];
musiccast =
ps: with ps; [
aiomusiccast
];
nicovideo = ps: [
]; # missing niconico.py-ma
musicme = ps: [
];
neteasecloudmusic = ps: [
];
nicovideo =
ps: with ps; [
pydantic
]; # missing niconico.py-ma
nts = ps: [
];
nugs = ps: [
];
opensubsonic =
@@ -147,6 +200,8 @@
];
qobuz = ps: [
];
qqmusic = ps: [
]; # missing qqmusic-api-python
radiobrowser =
ps: with ps; [
radios
@@ -158,13 +213,26 @@
async-upnp-client
rokuecp
];
samsung_wam = ps: [
]; # missing pywam
sendspin =
ps: with ps; [
ps:
with ps;
[
aiosendspin
av
];
]
++ aiosendspin.optional-dependencies.server;
siriusxm = ps: [
]; # missing sxm
smart_fades =
ps: with ps; [
beat-this
nnaudio
threadpoolctl
];
smart_playlist = ps: [
];
snapcast =
ps: with ps; [
bidict
@@ -173,6 +241,20 @@
];
somafm = ps: [
];
sonic_analysis =
ps: with ps; [
huggingface-hub
pyyaml
threadpoolctl
torchlibrosa
transformers
];
sonic_similarity =
ps: with ps; [
huggingface-hub
transformers
usearch
];
sonos =
ps: with ps; [
aiosonos
@@ -220,8 +302,20 @@
ps: with ps; [
aiovban
];
webdav = ps: [
];
wiim =
ps: with ps; [
wiim
];
wikipedia = ps: [
];
yandex_music = ps: [
]; # missing yandex-music
]; # missing yandex-music, ya-passport-auth
yandex_smarthome = ps: [
]; # missing ya-passport-auth
yandex_ynison = ps: [
]; # missing ya-passport-auth
yousee = ps: [
];
ytmusic =
@@ -232,6 +326,7 @@
ytmusicapi
]; # missing deno
zvuk_music = ps: [
]; # missing zvuk-music
];
# missing zvuk-music
};
}
@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -I nixpkgs=./. -i python3 -p "music-assistant.python.withPackages (ps: music-assistant.dependencies ++ (with ps; [ jinja2 packaging ]))" -p nixfmt pyright ruff isort
#!nix-shell -I nixpkgs=./. -i python3 -p "music-assistant.pythonPackages.python.withPackages (ps: music-assistant.dependencies ++ (with ps; [ jinja2 packaging ]))" -p nixfmt pyright ruff isort
import asyncio
import json
import os.path
@@ -24,13 +24,22 @@ TEMPLATE = """# Do not edit manually, run ./update-providers.py
{
version = "{{ version }}";
builtins = [
{%- for builtin in builtins | sort %}
"{{ builtin }}"
{%- endfor %}
];
providers = {
{%- for provider in providers | sort(attribute='domain') %}
{{ provider.domain }} = {% if provider.available %}ps: with ps;{% else %}ps:{% endif %} [
{%- for requirement in provider.available | sort %}
{{ requirement }}
{{ requirement }}
{%- endfor %}
];{% if provider.missing %} # missing {{ ", ".join(provider.missing) }}{% endif %}
]
{%- for requirement in provider.extra_list_deps | sort %}
++ {{ requirement }}
{%- endfor %}
;{% if provider.missing %} # missing {{ ", ".join(provider.missing) }}{% endif %}
{%- endfor %}
};
}
@@ -50,13 +59,16 @@ ROOT: Final = (
.strip()
)
PACKAGE_SET = "music-assistant.python.pkgs"
PACKAGE_SET = "music-assistant.pythonPackages"
PACKAGE_MAP = {
"git+https://github.com/MarvinSchenkel/pytube.git": "pytube",
}
EXTRA_DEPS = {
# Those providers cannot guard pydantic behind TYPE_CHECKING
"msx_bridge": ["pydantic"],
"nicovideo": ["pydantic"],
"ytmusic": [
# https://github.com/music-assistant/server/blob/2.5.8/music_assistant/providers/ytmusic/__init__.py#L120
"bgutil-ytdlp-pot-provider",
@@ -65,6 +77,11 @@ EXTRA_DEPS = {
}
EXTRA_LIST_DEPS = {
"sendspin": ["aiosendspin.optional-dependencies.server"],
}
def run_sync(cmd: List[str]) -> None:
print(f"$ {' '.join(cmd)}")
process = run(cmd)
@@ -143,7 +160,7 @@ def packageset_attributes():
ROOT,
"-qa",
"-A",
"music-assistant.python.pkgs",
"music-assistant.pythonPackages",
"--arg",
"config",
"{ allowAliases = false; }",
@@ -162,7 +179,7 @@ class NoMatch(Exception):
def resolve_package_attribute(package: str) -> str:
pattern = re.compile(rf"^music-assistant\.python\.pkgs\.{package}$", re.I)
pattern = re.compile(rf"^music-assistant\.pythonPackages\.{package}$", re.I)
packages = packageset_attributes()
matches = []
for attr in packages.keys():
@@ -189,6 +206,7 @@ class Provider:
domain: str
available: list[str] = field(default_factory=list)
missing: list[str] = field(default_factory=list)
extra_list_deps: list[str] = field(default_factory=list)
def __eq__(self, other):
return self.domain == other.domain
@@ -197,12 +215,12 @@ class Provider:
return hash(self.domain)
async def resolve_providers(manifests) -> Set:
async def resolve_providers(manifests) -> tuple[Set, Set]:
errors = []
providers = set()
for manifest in manifests:
provider = Provider(manifest.domain)
requirements = manifest.requirements + EXTRA_DEPS.get(manifest.domain, [])
requirements = manifest.requirements
for requirement in requirements:
# allow substituting requirement specifications that packaging cannot parse
if requirement in PACKAGE_MAP:
@@ -223,26 +241,37 @@ async def resolve_providers(manifests) -> Set:
version = await get_package_version(attr)
if version not in requirement.specifier:
errors.append(f"{requirement} not satisfied by version {version}")
if manifest.domain in EXTRA_DEPS:
for requirement in EXTRA_DEPS[manifest.domain]:
provider.available.append(requirement)
if manifest.domain in EXTRA_LIST_DEPS:
for requirement in EXTRA_LIST_DEPS[manifest.domain]:
provider.extra_list_deps.append(requirement)
providers.add(provider)
if errors:
print("\n - ", end="")
print("\n - ".join(errors))
return providers
builtins = {manifest.domain for manifest in manifests if manifest.builtin}
return providers, builtins
def render(outpath: str, version: str, providers: Set):
def render(outpath: str, version: str, providers: Set, builtins: Set):
env = Environment()
template = env.from_string(TEMPLATE)
template.stream(version=version, providers=providers).dump(outpath)
template.stream(version=version, providers=providers, builtins=builtins).dump(
outpath
)
async def main():
version: str = cast(str, await Nix.eval("music-assistant.version"))
manifests = await get_provider_manifests(version)
providers = await resolve_providers(manifests)
providers, builtins = await resolve_providers(manifests)
outpath = os.path.join(ROOT, "pkgs/by-name/mu/music-assistant/providers.nix")
render(outpath, version, providers)
render(outpath, version, providers, builtins)
run_sync(["nixfmt", outpath])
+1 -1
View File
@@ -36,7 +36,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
dependencies = with python3Packages; [
pygobject3
mpd2
python-mpd2
];
dontWrapGApps = true;
+1 -1
View File
@@ -20,7 +20,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
dependencies = with python3Packages; [
mutagen
mpd2
python-mpd2
toml
appdirs
];
+2 -2
View File
@@ -17,7 +17,7 @@ let
buildPythonApplication
dbus-python
pygobject3
mpd2
python-mpd2
setuptools
;
in
@@ -53,7 +53,7 @@ buildPythonApplication (finalAttrs: {
# included because it's difficult to build.
pythonPath = [
dbus-python
mpd2
python-mpd2
pygobject3
setuptools # pkg_resources is imported during runtime
];
+1 -1
View File
@@ -22,7 +22,7 @@ python3Packages.buildPythonPackage rec {
dependencies = with python3Packages; [
pyyaml
psutil
mpd2
python-mpd2
requests
];
@@ -29,17 +29,17 @@
buildPythonPackage (finalAttrs: {
pname = "aiosendspin";
version = "4.4.0";
version = "6.0.5";
pyproject = true;
src = fetchFromGitHub {
owner = "Sendspin";
repo = "aiosendspin";
tag = finalAttrs.version;
hash = "sha256-7edFCGNbECW5rrTbF7vJ4lJUc2IrQZD9VTR3IxJRP08=";
hash = "sha256-veX6MZSqEQb+tEqZTEgdCObLdaVPJEdTFW5Ivmb0TNQ=";
};
# https://github.com/Sendspin/aiosendspin/blob/4.4.0/pyproject.toml#L7
# https://github.com/Sendspin/aiosendspin/blob/5.3.0/pyproject.toml#L27
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail 'version = "0.0.0"' 'version = "${finalAttrs.version}"'
@@ -54,20 +54,26 @@ buildPythonPackage (finalAttrs: {
dependencies = [
aiohttp
av
mashumaro
numpy
orjson
pillow
zeroconf
];
optional-dependencies = {
server = [
av
numpy
pillow
];
};
nativeCheckInputs = [
pytest-aiohttp
pytest-cov-stub
pytest-xdist
pytestCheckHook
];
]
++ finalAttrs.passthru.optional-dependencies.server;
pythonImportsCheck = [
"aiosendspin"
@@ -0,0 +1,44 @@
{
lib,
setproctitle,
uvloop,
aiovban,
buildPythonPackage,
pyaudio,
setuptools,
}:
buildPythonPackage (finalAttrs: {
pname = "aiovban-pyaudio";
inherit (aiovban) version pyproject src;
sourceRoot = "${aiovban.src.name}/aiovban_pyaudio";
build-system = [ setuptools ];
dependencies = [
aiovban
pyaudio
];
pythonImportsCheck = [
"aiovban_pyaudio"
];
optional-dependencies = {
cli = [
setproctitle
uvloop
];
};
__structuredAttrs = true;
meta = {
changelog = "https://github.com/wmbest2/aiovban/releases/tag/${finalAttrs.src.tag}";
description = "PyAudio wrapper for aiovban";
homepage = "https://github.com/wmbest2/aiovban/tree/main/aiovban_pyaudio";
license = lib.licenses.mit;
inherit (aiovban.meta) maintainers;
};
})
@@ -1,32 +1,52 @@
{
lib,
aiovban-pyaudio,
buildPythonPackage,
fetchFromGitHub,
setuptools,
pytestCheckHook,
textual,
uv-build,
music-assistant,
}:
buildPythonPackage (finalAttrs: {
pname = "aiovban";
version = "0.7.0";
version = "1.1.0";
pyproject = true;
src = fetchFromGitHub {
owner = "wmbest2";
repo = "aiovban";
tag = "v${finalAttrs.version}";
hash = "sha256-0mhpmpsV0zSOWbhrPF9bfR9xAtJe6X57guWDZWMH6f0=";
hash = "sha256-yPp4+aQGJISTIFI/OoO7+mAR8daEytxrQn21SsFWEyc=";
};
build-system = [ setuptools ];
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "uv_build>=0.10.0,<0.11.0" "uv_build"
'';
nativeCheckInputs = [ pytestCheckHook ];
build-system = [ uv-build ];
dependencies = [ textual ];
# avoid infinite recursion with aiovban-pyaudio
doCheck = false;
nativeCheckInputs = [
aiovban-pyaudio
pytestCheckHook
]
++ aiovban-pyaudio.optional-dependencies.cli;
pythonImportsCheck = [
"aiovban"
];
passthru.tests = finalAttrs.finalPackage.overrideAttrs (_: {
doInstallCheck = true;
});
meta = {
changelog = "https://github.com/wmbest2/aiovban/releases/tag/${finalAttrs.src.tag}";
description = "Asyncio VBAN Protocol Wrapper";
@@ -0,0 +1,73 @@
{
lib,
buildPythonPackage,
einops,
fetchFromGitHub,
fetchurl,
numpy,
pytestCheckHook,
rotary-embedding-torch,
setuptools,
soundfile,
soxr,
torch,
torchaudio,
writableTmpDirAsHomeHook,
}:
buildPythonPackage (finalAttrs: {
pname = "beat-this";
version = "1.1.0";
pyproject = true;
src = fetchFromGitHub {
owner = "CPJKU";
repo = "beat_this";
tag = "v${finalAttrs.version}";
hash = "sha256-AEcDptPn5FUBb8+FuYSKjd00sFY5z6bS2iEOU64jido=";
};
build-system = [ setuptools ];
dependencies = [
einops
numpy
rotary-embedding-torch
soxr
torch
torchaudio
];
nativeCheckInputs = [
pytestCheckHook
soundfile
writableTmpDirAsHomeHook
];
preCheck = ''
mkdir -p $HOME/.cache/torch/hub/checkpoints/
cp ${finalAttrs.passthru.final0Ckpt} $HOME/.cache/torch/hub/checkpoints/beat_this-final0.ckpt
'';
pythonImportsCheck = [ "beat_this" ];
passthru = {
# The program prints the download URLs in the error message when it cannot download things in the nix sandbox
final0Ckpt = fetchurl {
url = "https://cloud.cp.jku.at/public.php/dav/files/7ik4RrBKTS273gp/final0.ckpt";
hash = "sha256-jDKLRfWdjdPf8hklP/ao1kgr5X0BM6KRQOL+u/jrgzE=";
};
small0Ckpt = fetchurl {
url = "https://cloud.cp.jku.at/public.php/dav/files/7ik4RrBKTS273gp/small0.ckpt";
hash = "sha256-YHS+LE1JDF9hAfzDdKHscq6TRW4ju2AZeDuEn13H1Hs=";
};
};
meta = {
description = "Accurate and general beat tracker";
homepage = "https://github.com/CPJKU/beat_this";
changelog = "https://github.com/CPJKU/beat_this/blob/main/CHANGELOG.md";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ SuperSandro2000 ];
};
})
@@ -70,7 +70,7 @@
librosa,
mp3gain,
mp3val,
mpd2,
python-mpd2,
pyacoustid,
pylast,
pyxdg,
@@ -350,9 +350,9 @@ buildPythonPackage (finalAttrs: {
mbpseudo = { };
metasync.testPaths = [ ];
missing.testPaths = [ ];
mpdstats.propagatedBuildInputs = [ mpd2 ];
mpdstats.propagatedBuildInputs = [ python-mpd2 ];
mpdupdate = {
propagatedBuildInputs = [ mpd2 ];
propagatedBuildInputs = [ python-mpd2 ];
testPaths = [ ];
};
musicbrainz = { };
@@ -0,0 +1,132 @@
{
lib,
buildPythonPackage,
fastmcp,
# build-system
hatchling,
uv-dynamic-versioning,
# dependencies
anthropic,
authlib,
azure-identity,
cyclopts,
exceptiongroup,
google-genai,
griffelib,
httpx,
jsonref,
jsonschema-path,
mcp,
openai,
openapi-pydantic,
opentelemetry-api,
packaging,
platformdirs,
py-key-value-aio,
pydantic,
pydantic-monty,
pydantic-settings,
pydocket,
pyjwt,
pyperclip,
python-dotenv,
python-multipart,
pyyaml,
rich,
typing-extensions,
uncalled-for,
uvicorn,
watchfiles,
websockets,
}:
buildPythonPackage (finalAttrs: {
pname = "fastmcp-slim";
inherit (fastmcp) version src;
sourceRoot = "${finalAttrs.src.name}/fastmcp_slim";
pyproject = true;
build-system = [
hatchling
uv-dynamic-versioning
];
dependencies = [
platformdirs
pydantic
pydantic-settings
python-dotenv
rich
typing-extensions
]
++ pydantic.optional-dependencies.email;
optional-dependencies = {
anthropic = [ anthropic ];
apps = [
# unpackaged prefab-ui
];
azure = [
azure-identity
pyjwt
];
client = [
authlib
]
++ finalAttrs.passthru.optional-dependencies.mcp
++ py-key-value-aio.optional-dependencies.filetree
++ py-key-value-aio.optional-dependencies.keyring
++ py-key-value-aio.optional-dependencies.memory;
code-mode = [ pydantic-monty ];
gemini = [
google-genai
jsonref
];
mcp = [
exceptiongroup
httpx
mcp
opentelemetry-api
];
openai = [ openai ];
server = [
authlib
cyclopts
griffelib
jsonref
jsonschema-path
openapi-pydantic
packaging
py-key-value-aio
pyperclip
python-multipart
pyyaml
uncalled-for
uvicorn
watchfiles
websockets
]
++ finalAttrs.passthru.optional-dependencies.mcp
++ py-key-value-aio.optional-dependencies.filetree
++ py-key-value-aio.optional-dependencies.keyring
++ py-key-value-aio.optional-dependencies.memory;
tasks = [
pydocket
];
};
pythonImportsCheck = [ "fastmcp" ];
# tests are done in fastmcp package
doCheck = false;
meta = {
description = "Dependency-slim FastMCP package";
changelog = "https://github.com/jlowin/fastmcp/releases/tag/${finalAttrs.src.tag}";
homepage = "https://github.com/PrefectHQ/fastmcp/tree/main/fastmcp_slim";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ GaetanLepage ];
};
})
@@ -10,54 +10,26 @@
uv-dynamic-versioning,
# dependencies
anthropic,
authlib,
azure-identity,
cyclopts,
exceptiongroup,
griffelib,
httpx,
jsonref,
jsonschema-path,
mcp,
fakeredis,
google-genai,
openai,
openapi-pydantic,
opentelemetry-api,
packaging,
platformdirs,
py-key-value-aio,
pydantic,
pydantic-monty,
pydocket,
pyjwt,
pyperclip,
python-dotenv,
pyyaml,
rich,
uncalled-for,
uvicorn,
watchfiles,
websockets,
fastmcp-slim,
# tests
dirty-equals,
email-validator,
fastapi,
inline-snapshot,
lupa,
opentelemetry-sdk,
psutil,
pytest-asyncio,
pytest-examples,
pytest-httpx,
pytest-rerunfailures,
pytest-timeout,
pytest-xdist,
pytestCheckHook,
}:
buildPythonPackage (finalAttrs: {
pname = "fastmcp";
version = "3.2.4";
version = "3.3.1";
pyproject = true;
__structuredAttrs = true;
@@ -65,7 +37,7 @@ buildPythonPackage (finalAttrs: {
owner = "PrefectHQ";
repo = "fastmcp";
tag = "v${finalAttrs.version}";
hash = "sha256-rJpxPvqAaa6/vXhG1+R9dI32cY/54e6I+F/zyBVoqBM=";
hash = "sha256-1W5NbWIULxFXGSozZEeITcPt1EbY6IsJLQdyevcn9BI=";
};
build-system = [
@@ -73,121 +45,66 @@ buildPythonPackage (finalAttrs: {
uv-dynamic-versioning
];
pythonRelaxDeps = [
"py-key-value-aio"
"pydocket"
];
dependencies = [
authlib
cyclopts
exceptiongroup
griffelib
httpx
jsonref
jsonschema-path
mcp
openapi-pydantic
opentelemetry-api
packaging
platformdirs
py-key-value-aio
pydantic
pyperclip
python-dotenv
pyyaml
rich
uncalled-for
uvicorn
watchfiles
websockets
fastmcp-slim
]
++ py-key-value-aio.optional-dependencies.filetree
++ py-key-value-aio.optional-dependencies.keyring
++ py-key-value-aio.optional-dependencies.memory
++ pydantic.optional-dependencies.email;
++ fastmcp-slim.optional-dependencies.client
++ fastmcp-slim.optional-dependencies.server;
optional-dependencies = {
anthropic = [ anthropic ];
azure = [
azure-identity
pyjwt
];
code-mode = [ pydantic-monty ];
gemini = [ google-genai ];
openai = [ openai ];
tasks = [
pydocket
fakeredis
]
++ fakeredis.optional-dependencies.lua;
anthropic = fastmcp-slim.optional-dependencies.anthropic;
apps = fastmcp-slim.optional-dependencies.apps;
azure = fastmcp-slim.optional-dependencies.azure;
code-mode = fastmcp-slim.optional-dependencies.code-mode;
gemini = fastmcp-slim.optional-dependencies.gemini;
openai = fastmcp-slim.optional-dependencies.openai;
tasks = fastmcp-slim.optional-dependencies.tasks;
};
pythonImportsCheck = [ "fastmcp" ];
nativeCheckInputs = [
dirty-equals
email-validator
fastapi
inline-snapshot
lupa
opentelemetry-sdk
psutil
pytest-asyncio
pytest-examples
pytest-httpx
pytest-rerunfailures
pytest-timeout
pytest-xdist
pytestCheckHook
writableTmpDirAsHomeHook
]
++ finalAttrs.passthru.optional-dependencies.anthropic
++ finalAttrs.passthru.optional-dependencies.apps
++ finalAttrs.passthru.optional-dependencies.azure
++ finalAttrs.passthru.optional-dependencies.code-mode
++ finalAttrs.passthru.optional-dependencies.gemini
++ finalAttrs.passthru.optional-dependencies.openai
++ finalAttrs.passthru.optional-dependencies.tasks
++ inline-snapshot.optional-dependencies.dirty-equals;
disabledTests = [
# requires internet
"test_github_api_schema_performance"
# RuntimeError: Client failed to connect: Connection closed
"test_keep_alive_maintains_session_across_multiple_calls"
"test_keep_alive_false_starts_new_session_across_multiple_calls"
"test_keep_alive_false_exit_scope_kills_server"
"test_keep_alive_starts_new_session_if_manually_closed"
"test_keep_alive_true_exit_scope_kills_client"
"test_keep_alive_maintains_session_if_reentered"
"test_close_session_and_try_to_use_client_raises_error"
"test_parallel_calls"
"test_single_server_config_include_tags_filtering"
"test_run_mcp_config"
"test_settings_from_environment_issue_1749"
# requires uv
"test_uv_transport"
"test_uv_transport_module"
"test_github_api_schema_performance"
# Hang forever
"test_nested_streamable_http_server_resolves_correctly"
# RuntimeError: Client failed to connect: Timed out while waiting for response
"test_timeout"
"test_timeout_tool_call_overrides_client_timeout_even_if_lower"
# Requires prefab-ui (optional dependency)
"test_auto_registers_renderer_resource"
"test_auto_synthesizes_renderer_resource"
"test_equivalent_to_app_true"
# Requires pydocket (tasks optional dependency, not in test inputs)
"test_mounted_server_does_not_have_docket"
"test_get_tasks_returns_task_eligible_tools"
"test_task_teardown_does_not_hang"
"test_background_task_can_read_snapshotted_request_headers"
"test_background_task_current_http_dependencies_restore_headers"
"test_task_execution_auto_populated_for_task_enabled_tool"
"test_function_tool_task_config_still_works"
"test_async_partial_with_task_true_does_not_raise"
"test_sync_partial_with_task_true_raises"
"test_is_docket_available"
"test_require_docket_passes_when_installed"
# Shared dependency caching differs in sandbox
"TestSharedDependencies"
"TestPrefabAppConfig"
"test_doc_examples_quality"
# AssertionError: assert 'INFO' == 'DEBUG'
"test_temporary_settings"
@@ -195,36 +112,21 @@ buildPythonPackage (finalAttrs: {
# Subprocess-based multi-client tests fail in sandbox
"test_multi_client"
"test_multi_server"
"test_single_server_config_include_tags_filtering"
"test_server_starts_without_auth"
"test_canonical_multi_client_with_transforms"
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
# RuntimeError: Server failed to start after 10 attempts
"test_unauthorized_access"
"test_stateless_proxy"
++ lib.optionals stdenv.hostPlatform.isAarch64 [
# floating point error
"test_index_retrieval[float32-quantization1-1-metric0-3]"
];
disabledTestPaths = [
# Requires prefab-ui (optional dependency)
"tests/apps"
"tests/docs/test_doc_examples.py"
"tests/test_apps_prefab.py"
"tests/test_fastmcp_app.py"
# Subprocess crash recovery tests are flaky in sandbox
"tests/client/test_stdio.py"
# Requires pydocket/fakeredis (tasks optional dependency, not in test inputs)
"tests/server/tasks"
"tests/server/test_server_docket.py"
"tests/client/tasks"
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
# RuntimeError: Server failed to start after 10 attempts
"tests/client/auth/test_oauth_client.py"
"tests/client/test_sse.py"
"tests/client/test_streamable_http.py"
"tests/server/auth/test_jwt_provider.py"
"tests/server/http/test_http_dependencies.py"
];
__darwinAllowLocalNetworking = true;
@@ -0,0 +1,80 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
fetchurl,
librosa,
numpy,
pytestCheckHook,
setuptools,
scipy,
stdenv,
torch,
writableTmpDirAsHomeHook,
}:
let
choice = fetchurl {
url = "https://librosa.org/data/audio/admiralbob77_-_Choice_-_Drum-bass.ogg";
hash = "sha256-rGRPlkXnwVF05KT4Vh5NFEjX9uWf9rBVazEOu87Yebw=";
};
vibeace = fetchurl {
url = "https://librosa.org/data/audio/Kevin_MacLeod_-_Vibe_Ace.ogg";
hash = "sha256-bCOu091apX8rFlLsq2jRXZuCrSV/VOY56yiAygm8EYo=";
};
in
buildPythonPackage (finalAttrs: {
pname = "nnaudio";
version = "0.3.4";
pyproject = true;
src = fetchFromGitHub {
owner = "KinWaiCheuk";
repo = "nnAudio";
rev = "e77d9f874cf37b273f44f68aefbd32fb0b979912";
hash = "sha256-uJySa2A7IbuY/9Wq/w9gRkBk1NhMrhipyclOWO5koHE=";
};
sourceRoot = "${finalAttrs.src.name}/Installation";
build-system = [ setuptools ];
dependencies = [
numpy
scipy
torch
];
nativeCheckInputs = [
librosa
pytestCheckHook
writableTmpDirAsHomeHook
];
preCheck = ''
mkdir -p $HOME/.cache/librosa/
cp ${choice} $HOME/.cache/librosa/admiralbob77_-_Choice_-_Drum-bass.ogg
cp ${vibeace} $HOME/.cache/librosa/Kevin_MacLeod_-_Vibe_Ace.ogg
export NUMBA_CACHE_DIR=$(mktemp -d)
'';
disabledTests = [
# AttributeError: module 'scipy.signal' has no attribute 'blackmanharris'
"test_cfp_original[cpu]"
"test_cfp_new[cpu]"
# Test fixture matrix has other values
"test_vqt_gamma_zero[cpu]"
]
++ lib.optionals (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isAarch64) [
# Test fixture matrix has other values
"test_cqt_1992_v2_log[cpu]"
];
pythonImportsCheck = [ "nnAudio" ];
meta = {
description = "Fast GPU audio processing toolbox with 1D convolutional neural network";
homepage = "https://github.com/KinWaiCheuk/nnAudio";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ SuperSandro2000 ];
};
})
@@ -1,23 +1,24 @@
{
lib,
aiohttp,
buildPythonPackage,
fetchFromGitHub,
setuptools,
aiohttp,
mashumaro,
requests,
pytest-asyncio,
pytestCheckHook,
setuptools,
}:
buildPythonPackage rec {
pname = "py-opensonic";
version = "9.1.0";
version = "10.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "khers";
repo = "py-opensonic";
tag = "v${version}";
hash = "sha256-xZHlI62QoKkR4sZf0GUEzUGMpG2urHooPs8GvVyqpIQ=";
hash = "sha256-LT6pTtXCUMhk6uV9Y2inlAuP8osWUwsWOH7/yOW2OXI=";
};
build-system = [ setuptools ];
@@ -25,10 +26,16 @@ buildPythonPackage rec {
dependencies = [
aiohttp
mashumaro
requests
];
doCheck = false; # no tests
pythonRelaxDeps = [
"mashumaro"
];
nativeCheckInputs = [
pytest-asyncio
pytestCheckHook
];
pythonImportsCheck = [
"libopensonic"
@@ -1,25 +1,25 @@
{
aiohttp,
aioresponses,
buildPythonPackage,
fetchFromGitHub,
hatchling,
lib,
lxml,
mocket,
pytest-asyncio,
pytestCheckHook,
}:
buildPythonPackage rec {
pname = "pyblu";
version = "2.0.6";
version = "2.0.8";
pyproject = true;
src = fetchFromGitHub {
owner = "LouisChrist";
repo = "pyblu";
tag = "v${version}";
hash = "sha256-qLB9o40tRYgmbYJEEx8r3SodH1hB8MM4yLXbdKIs/xA=";
hash = "sha256-uYYiu0V491eHg47Rc9HGEiddONnFqGuPj34Mkfk5Gnk=";
};
pythonRelaxDeps = [ "aiohttp" ];
@@ -34,11 +34,17 @@ buildPythonPackage rec {
pythonImportsCheck = [ "pyblu" ];
nativeCheckInputs = [
aioresponses
mocket
pytest-asyncio
pytestCheckHook
];
disabledTestPaths = [
# all tests fail with:
# aiohttp.client_exceptions.ClientConnectorDNSError: Cannot connect to host node:11000 ssl:default [Could not contact DNS servers]
"tests/test_player.py"
];
meta = {
changelog = "https://github.com/LouisChrist/pyblu/releases/tag/${src.tag}";
description = "BluOS API client";
@@ -16,7 +16,7 @@
dbus-fast,
iwlib,
libcst,
mpd2,
python-mpd2,
prompt-toolkit,
psutil,
pulsectl-asyncio,
@@ -118,7 +118,7 @@ buildPythonPackage (finalAttrs: {
dbus-fast
iwlib
libcst
mpd2
python-mpd2
# prompt-toolkit used for qtile repl
# see https://github.com/qtile/qtile/blob/master/libqtile/scripts/repl.py
prompt-toolkit
@@ -8,6 +8,7 @@
numpy,
pulsectl-asyncio,
pychromecast,
pytest-asyncio,
pytestCheckHook,
qrcode,
readchar,
@@ -18,14 +19,14 @@
buildPythonPackage (finalAttrs: {
pname = "sendspin";
version = "5.9.0";
version = "7.4.0";
pyproject = true;
src = fetchFromGitHub {
owner = "Sendspin";
repo = "sendspin-cli";
tag = finalAttrs.version;
hash = "sha256-g+qw3mDHij50CEDKGjltMGNZoI6/HeJQ8zq8NSvD3Ls=";
hash = "sha256-B375jsOik0IdLtozH3t3hZKqoO+dtqkzX2bk5YuoO9Y=";
};
postPatch = ''
@@ -45,20 +46,23 @@ buildPythonPackage (finalAttrs: {
readchar
rich
sounddevice
];
]
++ aiosendspin.optional-dependencies.server;
optional-dependencies = {
cast = [ pychromecast ];
};
nativeCheckInputs = [ pytestCheckHook ];
nativeCheckInputs = [
pytest-asyncio
pytestCheckHook
];
pythonImportsCheck = [ "sendspin" ];
disabledTests = [
# AssertionError: assert None == (1, 'Digital')
"test_alsa_available_for_hw_device_with_mixer"
"test_hifiberry_dac_discovery"
# requires internet
"test_multi_worker_starts_and_serves_status"
];
meta = {
@@ -4,6 +4,7 @@
buildPythonPackage,
fetchPypi,
setuptools,
setuptools-scm,
cffi,
numpy,
portaudio,
@@ -12,15 +13,18 @@
buildPythonPackage rec {
pname = "sounddevice";
version = "0.5.3";
version = "0.5.5";
pyproject = true;
src = fetchPypi {
inherit pname version;
hash = "sha256-y6wrYBmPurhFM2l+fEkEzIlexp1fs5c1VsnrdKRimyw=";
hash = "sha256-Ikh7ZRmMtb8iCHVRBbUk94rRc+Wra0Rb2rHJifZpjfM=";
};
build-system = [ setuptools ];
build-system = [
setuptools
setuptools-scm
];
dependencies = [
cffi
@@ -43,7 +47,8 @@ buildPythonPackage rec {
meta = {
description = "Play and Record Sound with Python";
homepage = "http://python-sounddevice.rtfd.org/";
homepage = "https://python-sounddevice.readthedocs.io/";
changelog = "https://github.com/spatialaudio/python-sounddevice/releases/tag/${version}";
license = with lib.licenses; [ mit ];
};
}
@@ -1,8 +1,8 @@
diff --git a/sounddevice.py b/sounddevice.py
index 0974289..2d56c28 100644
--- a/sounddevice.py
+++ b/sounddevice.py
@@ -58,32 +58,7 @@ from ctypes.util import find_library as _find_library
diff --git a/src/sounddevice.py b/src/sounddevice.py
index 00fc6f8..72abede 100644
--- a/src/sounddevice.py
+++ b/src/sounddevice.py
@@ -59,36 +59,7 @@
from _sounddevice import ffi as _ffi
@@ -17,22 +17,26 @@ index 0974289..2d56c28 100644
- break
- else:
- raise OSError('PortAudio library not found')
- _lib = _ffi.dlopen(_libname)
- _lib: ... = _ffi.dlopen(_libname)
-except OSError:
- if _platform.system() == 'Darwin':
- _libname = 'libportaudio.dylib'
- elif _platform.system() == 'Windows':
- if 'SD_ENABLE_ASIO' in _os.environ:
- _libname = 'libportaudio' + _platform.architecture()[0] + '-asio.dll'
- if _platform.machine().lower() in ('arm64', 'aarch64'):
- _platform_suffix = 'arm64'
- else:
- _libname = 'libportaudio' + _platform.architecture()[0] + '.dll'
- _platform_suffix = _platform.architecture()[0]
- if 'SD_ENABLE_ASIO' in _os.environ:
- _libname = 'libportaudio' + _platform_suffix + '-asio.dll'
- else:
- _libname = 'libportaudio' + _platform_suffix + '.dll'
- else:
- raise
- import _sounddevice_data
- _libname = _os.path.join(
- next(iter(_sounddevice_data.__path__)), 'portaudio-binaries', _libname)
- _lib = _ffi.dlopen(_libname)
+_lib = _ffi.dlopen('@portaudio@')
- _lib: ... = _ffi.dlopen(_libname)
+_lib: ... = _ffi.dlopen('@portaudio@')
_sampleformats = {
_sampleformats: ... = {
'float32': _lib.paFloat32,
@@ -4245,7 +4245,7 @@
];
"mpd" =
ps: with ps; [
mpd2
python-mpd2
];
"mqtt" =
ps: with ps; [
+2
View File
@@ -1855,6 +1855,8 @@ with pkgs;
cffconvert = python3Packages.toPythonApplication python3Packages.cffconvert;
aiovban-pyaudio = python3Packages.toPythonApplication python3Packages.aiovban-pyaudio;
clickhouse-lts = callPackage ../by-name/cl/clickhouse/lts.nix { };
cmdpack = callPackages ../tools/misc/cmdpack { };
+1
View File
@@ -368,6 +368,7 @@ mapAliases {
monarchmoney = throw "'monarchmoney' has been renamed to/replaced by 'monarchmoneycommunity'"; # Added 2026-03-05
monkeytype = throw "'monkeytype' has been removed as it was unmaintained upstream"; # Added 2026-04-19
moretools = "'moretools' has been removed because it is unmaintained"; # Added 2026-01-19
mpd2 = warnAlias "'mpd2' has been renamed to 'python-mpd2'"; # Added 2026-06-14
mpire = throw "'mpire' has been removed because it is unused in Nixpkgs"; # Added 2026-06-22
msldap-bad = throw "'msldap-bad' has been renamed to/replaced by 'badldap'"; # added 2025-11-06
mullvad-closest = throw "'mullvad-closest' has been removed as it was unmaintained. Consider using 'mullvad-compass' instead."; # Added 2026-01-13
+10 -2
View File
@@ -578,6 +578,8 @@ self: super: with self; {
aiovban = callPackage ../development/python-modules/aiovban { };
aiovban-pyaudio = callPackage ../development/python-modules/aiovban-pyaudio { };
aiovlc = callPackage ../development/python-modules/aiovlc { };
aiovodafone = callPackage ../development/python-modules/aiovodafone { };
@@ -2030,6 +2032,8 @@ self: super: with self; {
beartype = callPackage ../development/python-modules/beartype { };
beat-this = callPackage ../development/python-modules/beat-this { };
beaupy = callPackage ../development/python-modules/beaupy { };
beautiful-date = callPackage ../development/python-modules/beautiful-date { };
@@ -5589,6 +5593,8 @@ self: super: with self; {
fastmcp = callPackage ../development/python-modules/fastmcp { };
fastmcp-slim = callPackage ../development/python-modules/fastmcp-slim { };
fastmri = callPackage ../development/python-modules/fastmri { };
fastnlo-toolkit = toPythonModule (
@@ -10547,8 +10553,6 @@ self: super: with self; {
callPackage ../development/python-modules/mozjpeg_lossless_optimization
{ };
mpd2 = callPackage ../development/python-modules/mpd2 { };
mpegdash = callPackage ../development/python-modules/mpegdash { };
mpi-pytest = callPackage ../development/python-modules/mpi-pytest { };
@@ -11463,6 +11467,8 @@ self: super: with self; {
nmcli = callPackage ../development/python-modules/nmcli { };
nnaudio = callPackage ../development/python-modules/nnaudio { };
nnpdf = toPythonModule (pkgs.nnpdf.override { python3 = python; });
noaa-coops = callPackage ../development/python-modules/noaa-coops { };
@@ -16299,6 +16305,8 @@ self: super: with self; {
python-motionmount = callPackage ../development/python-modules/python-motionmount { };
python-mpd2 = callPackage ../development/python-modules/python-mpd2 { };
python-mpv-jsonipc = callPackage ../development/python-modules/python-mpv-jsonipc { };
python-multipart = callPackage ../development/python-modules/python-multipart { };