about summary refs log tree commit diff
path: root/nixpkgs/pkgs/servers/home-assistant
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2022-03-15 10:36:38 +0000
committerAlyssa Ross <hi@alyssa.is>2022-03-16 11:37:19 +0000
commitd435710923ac6e6f9fc155534800745004f2ce93 (patch)
tree386f9401476f96bdc6ec25173a090198942b5d5b /nixpkgs/pkgs/servers/home-assistant
parentc725f0011e91ae49d351b981690eb66b862b6104 (diff)
parent3239fd2b8f728106491154b44625662e10259af2 (diff)
downloadnixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar.gz
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar.bz2
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar.lz
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar.xz
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.tar.zst
nixlib-d435710923ac6e6f9fc155534800745004f2ce93.zip
Merge commit '3239fd2b8f728106491154b44625662e10259af2'
Conflicts:
	nixpkgs/pkgs/applications/window-managers/sway/default.nix
Diffstat (limited to 'nixpkgs/pkgs/servers/home-assistant')
-rw-r--r--nixpkgs/pkgs/servers/home-assistant/component-packages.nix43
-rw-r--r--nixpkgs/pkgs/servers/home-assistant/default.nix34
-rw-r--r--nixpkgs/pkgs/servers/home-assistant/frontend.nix4
-rwxr-xr-xnixpkgs/pkgs/servers/home-assistant/parse-requirements.py45
-rw-r--r--nixpkgs/pkgs/servers/home-assistant/tests.nix12
5 files changed, 85 insertions, 53 deletions
diff --git a/nixpkgs/pkgs/servers/home-assistant/component-packages.nix b/nixpkgs/pkgs/servers/home-assistant/component-packages.nix
index 714087eb2e60..bb750635d5d9 100644
--- a/nixpkgs/pkgs/servers/home-assistant/component-packages.nix
+++ b/nixpkgs/pkgs/servers/home-assistant/component-packages.nix
@@ -2,7 +2,7 @@
 # Do not edit!
 
 {
-  version = "2022.2.9";
+  version = "2022.3.4";
   components = {
     "abode" = ps: with ps; [ abodepy ];
     "accuweather" = ps: with ps; [ accuweather ];
@@ -44,7 +44,6 @@
     "apache_kafka" = ps: with ps; [ aiokafka ];
     "apcupsd" = ps: with ps; [ apcaccess ];
     "api" = ps: with ps; [ aiohttp-cors ];
-    "apns" = ps: with ps; [ ]; # missing inputs: apns2
     "apple_tv" = ps: with ps; [ aiohttp-cors ifaddr pyatv zeroconf ];
     "apprise" = ps: with ps; [ apprise ];
     "aprs" = ps: with ps; [ aprslib geopy ];
@@ -166,7 +165,7 @@
     "deconz" = ps: with ps; [ pydeconz ];
     "decora" = ps: with ps; [ bluepy ]; # missing inputs: decora
     "decora_wifi" = ps: with ps; [ ]; # missing inputs: decora_wifi
-    "default_config" = ps: with ps; [ pynacl pyturbojpeg aiodiscover aiohttp-cors async-upnp-client emoji hass-nabucasa home-assistant-frontend ifaddr pillow pyserial pyudev scapy sqlalchemy zeroconf ];
+    "default_config" = ps: with ps; [ pynacl pyturbojpeg aiodiscover aiohttp-cors async-upnp-client hass-nabucasa home-assistant-frontend ifaddr pillow pyserial pyudev scapy sqlalchemy zeroconf ];
     "delijn" = ps: with ps; [ pydelijn ];
     "deluge" = ps: with ps; [ deluge-client ];
     "demo" = ps: with ps; [ aiohttp-cors sqlalchemy ];
@@ -188,12 +187,13 @@
     "digitalloggers" = ps: with ps; [ ]; # missing inputs: dlipower
     "directv" = ps: with ps; [ directv ];
     "discogs" = ps: with ps; [ discogs-client ];
-    "discord" = ps: with ps; [ discordpy ];
+    "discord" = ps: with ps; [ nextcord ];
     "discovery" = ps: with ps; [ aiohttp-cors ifaddr netdisco zeroconf ];
     "dlib_face_detect" = ps: with ps; [ face_recognition ];
     "dlib_face_identify" = ps: with ps; [ face_recognition ];
     "dlink" = ps: with ps; [ ]; # missing inputs: pyW215
     "dlna_dmr" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr zeroconf ];
+    "dlna_dms" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr zeroconf ];
     "dnsip" = ps: with ps; [ aiodns ];
     "dominos" = ps: with ps; [ aiohttp-cors ]; # missing inputs: pizzapi
     "doods" = ps: with ps; [ pillow pydoods ];
@@ -216,7 +216,7 @@
     "ecobee" = ps: with ps; [ python-ecobee-api ];
     "econet" = ps: with ps; [ pyeconet ];
     "ecovacs" = ps: with ps; [ ]; # missing inputs: sucks
-    "eddystone_temperature" = ps: with ps; [ construct ]; # missing inputs: beacontools[scan]
+    "eddystone_temperature" = ps: with ps; [ construct ]; # missing inputs: beacontools
     "edimax" = ps: with ps; [ pyedimax ];
     "edl21" = ps: with ps; [ pysml ];
     "efergy" = ps: with ps; [ pyefergy ];
@@ -224,7 +224,7 @@
     "eight_sleep" = ps: with ps; [ pyeight ];
     "elgato" = ps: with ps; [ elgato ];
     "eliqonline" = ps: with ps; [ eliqonline ];
-    "elkm1" = ps: with ps; [ elkm1-lib ];
+    "elkm1" = ps: with ps; [ aiohttp-cors elkm1-lib ifaddr ];
     "elmax" = ps: with ps; [ elmax-api ];
     "elv" = ps: with ps; [ pypca ];
     "emby" = ps: with ps; [ pyemby ];
@@ -264,7 +264,7 @@
     "ffmpeg" = ps: with ps; [ ha-ffmpeg ];
     "ffmpeg_motion" = ps: with ps; [ ha-ffmpeg ];
     "ffmpeg_noise" = ps: with ps; [ ha-ffmpeg ];
-    "fibaro" = ps: with ps; [ ]; # missing inputs: fiblary3
+    "fibaro" = ps: with ps; [ fiblary3-fork ];
     "fido" = ps: with ps; [ pyfido ];
     "file" = ps: with ps; [ ];
     "filesize" = ps: with ps; [ ];
@@ -273,6 +273,7 @@
     "fireservicerota" = ps: with ps; [ pyfireservicerota ];
     "firmata" = ps: with ps; [ pymata-express ];
     "fitbit" = ps: with ps; [ aiohttp-cors fitbit ];
+    "fivem" = ps: with ps; [ ]; # missing inputs: fivem-api
     "fixer" = ps: with ps; [ fixerio ];
     "fjaraskupan" = ps: with ps; [ fjaraskupan ];
     "fleetgo" = ps: with ps; [ ritassist ];
@@ -324,7 +325,6 @@
     "gitlab_ci" = ps: with ps; [ python-gitlab ];
     "gitter" = ps: with ps; [ ]; # missing inputs: gitterpy
     "glances" = ps: with ps; [ glances-api ];
-    "gntp" = ps: with ps; [ gntp ];
     "goalfeed" = ps: with ps; [ ]; # missing inputs: pysher
     "goalzero" = ps: with ps; [ goalzero ];
     "gogogate2" = ps: with ps; [ ismartgate ];
@@ -446,7 +446,7 @@
     "kiwi" = ps: with ps; [ ]; # missing inputs: kiwiki-client
     "kmtronic" = ps: with ps; [ pykmtronic ];
     "knx" = ps: with ps; [ xknx ];
-    "kodi" = ps: with ps; [ pykodi ];
+    "kodi" = ps: with ps; [ aiohttp-cors pykodi ];
     "konnected" = ps: with ps; [ aiohttp-cors konnected ];
     "kostal_plenticore" = ps: with ps; [ ]; # missing inputs: kostal_plenticore
     "kraken" = ps: with ps; [ krakenex pykrakenapi ];
@@ -532,11 +532,12 @@
     "minio" = ps: with ps; [ minio ];
     "mitemp_bt" = ps: with ps; [ ]; # missing inputs: mitemp_bt
     "mjpeg" = ps: with ps; [ ];
-    "mobile_app" = ps: with ps; [ pynacl pyturbojpeg aiohttp-cors emoji hass-nabucasa pillow ];
+    "mobile_app" = ps: with ps; [ pynacl pyturbojpeg aiohttp-cors hass-nabucasa pillow ];
     "mochad" = ps: with ps; [ ]; # missing inputs: pymochad
     "modbus" = ps: with ps; [ pymodbus ];
     "modem_callerid" = ps: with ps; [ aiohttp-cors phone-modem pyserial pyudev ];
     "modern_forms" = ps: with ps; [ aiomodernforms ];
+    "moehlenhoff_alpha2" = ps: with ps; [ ]; # missing inputs: moehlenhoff-alpha2
     "mold_indicator" = ps: with ps; [ ];
     "monoprice" = ps: with ps; [ ]; # missing inputs: pymonoprice
     "moon" = ps: with ps; [ ];
@@ -680,6 +681,7 @@
     "proxy" = ps: with ps; [ pillow ];
     "ps4" = ps: with ps; [ ]; # missing inputs: pyps4-2ndscreen
     "pulseaudio_loopback" = ps: with ps; [ pulsectl ];
+    "pure_energie" = ps: with ps; [ gridnet ];
     "push" = ps: with ps; [ aiohttp-cors ];
     "pushbullet" = ps: with ps; [ pushbullet ];
     "pushover" = ps: with ps; [ pushover-complete ];
@@ -697,6 +699,7 @@
     "qwikswitch" = ps: with ps; [ ]; # missing inputs: pyqwikswitch
     "rachio" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa rachiopy ];
     "radarr" = ps: with ps; [ ];
+    "radio_browser" = ps: with ps; [ radios ];
     "radiotherm" = ps: with ps; [ radiotherm ];
     "rainbird" = ps: with ps; [ ]; # missing inputs: pyrainbird
     "raincloud" = ps: with ps; [ ]; # missing inputs: raincloudy
@@ -780,7 +783,7 @@
     "sia" = ps: with ps; [ pysiaalarm ];
     "sigfox" = ps: with ps; [ ];
     "sighthound" = ps: with ps; [ pillow simplehound ];
-    "signal_messenger" = ps: with ps; [ ]; # missing inputs: pysignalclirestapi
+    "signal_messenger" = ps: with ps; [ pysignalclirestapi ];
     "simplepush" = ps: with ps; [ ]; # missing inputs: simplepush
     "simplisafe" = ps: with ps; [ simplisafe-python ];
     "simulated" = ps: with ps; [ ];
@@ -791,7 +794,7 @@
     "skybeacon" = ps: with ps; [ pygatt ];
     "skybell" = ps: with ps; [ skybellpy ];
     "slack" = ps: with ps; [ slackclient ];
-    "sleepiq" = ps: with ps; [ sleepyq ];
+    "sleepiq" = ps: with ps; [ asyncsleepiq ];
     "slide" = ps: with ps; [ ]; # missing inputs: goslide-api
     "sma" = ps: with ps; [ pysma ];
     "smappee" = ps: with ps; [ aiohttp-cors pysmappee ];
@@ -814,7 +817,7 @@
     "soma" = ps: with ps; [ pysoma ];
     "somfy" = ps: with ps; [ aiohttp-cors pymfy ];
     "somfy_mylink" = ps: with ps; [ somfy-mylink-synergy ];
-    "sonarr" = ps: with ps; [ sonarr ];
+    "sonarr" = ps: with ps; [ aiopyarr ];
     "songpal" = ps: with ps; [ python-songpal ];
     "sonos" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr plexapi plexauth plexwebsocket soco spotipy zeroconf ];
     "sony_projector" = ps: with ps; [ pysdcp ];
@@ -924,7 +927,7 @@
     "twilio_call" = ps: with ps; [ aiohttp-cors twilio ];
     "twilio_sms" = ps: with ps; [ aiohttp-cors twilio ];
     "twinkly" = ps: with ps; [ ttls ];
-    "twitch" = ps: with ps; [ python-twitch-client ];
+    "twitch" = ps: with ps; [ twitchapi ];
     "twitter" = ps: with ps; [ twitterapi ];
     "ubus" = ps: with ps; [ openwrt-ubus-rpc ];
     "ue_smart_radio" = ps: with ps; [ ];
@@ -967,7 +970,7 @@
     "voicerss" = ps: with ps; [ ];
     "volkszaehler" = ps: with ps; [ volkszaehler ];
     "volumio" = ps: with ps; [ pyvolumio ];
-    "volvooncall" = ps: with ps; [ ]; # missing inputs: volvooncall
+    "volvooncall" = ps: with ps; [ volvooncall ];
     "vultr" = ps: with ps; [ vultr ];
     "w800rf32" = ps: with ps; [ ]; # missing inputs: pyW800rf32
     "wake_on_lan" = ps: with ps; [ wakeonlan ];
@@ -990,6 +993,7 @@
     "wilight" = ps: with ps; [ pywilight ];
     "wirelesstag" = ps: with ps; [ ]; # missing inputs: wirelesstagpy
     "withings" = ps: with ps; [ aiohttp-cors ]; # missing inputs: withings-api
+    "wiz" = ps: with ps; [ aiohttp-cors ifaddr pywizlight ];
     "wled" = ps: with ps; [ wled ];
     "wolflink" = ps: with ps; [ ]; # missing inputs: wolf_smartset
     "workday" = ps: with ps; [ holidays ];
@@ -998,7 +1002,6 @@
     "worxlandroid" = ps: with ps; [ ];
     "wsdot" = ps: with ps; [ ];
     "x10" = ps: with ps; [ ];
-    "xbee" = ps: with ps; [ ]; # missing inputs: xbee-helper
     "xbox" = ps: with ps; [ aiohttp-cors xbox-webapi ];
     "xbox_live" = ps: with ps; [ xboxapi ];
     "xeoma" = ps: with ps; [ pyxeoma ];
@@ -1031,6 +1034,7 @@
     "zoneminder" = ps: with ps; [ zm-py ];
     "zwave" = ps: with ps; [ homeassistant-pyozw pydispatcher ];
     "zwave_js" = ps: with ps; [ aiohttp-cors pyserial pyudev zwave-js-server-python ];
+    "zwave_me" = ps: with ps; [ aiohttp-cors ifaddr url-normalize zeroconf ]; # missing inputs: zwave_me_ws
   };
   # components listed in tests/components for which all dependencies are packaged
   supportedComponentsWithTests = [
@@ -1143,6 +1147,7 @@
     "directv"
     "discovery"
     "dlna_dmr"
+    "dlna_dms"
     "dnsip"
     "doorbird"
     "dsmr"
@@ -1343,6 +1348,7 @@
     "min_max"
     "minecraft_server"
     "minio"
+    "mjpeg"
     "mobile_app"
     "modbus"
     "modem_callerid"
@@ -1423,6 +1429,7 @@
     "prometheus"
     "prosegur"
     "proximity"
+    "pure_energie"
     "push"
     "pushbullet"
     "pvoutput"
@@ -1431,6 +1438,7 @@
     "qld_bushfire"
     "rachio"
     "radarr"
+    "radio_browser"
     "rainforest_eagle"
     "rainmachine"
     "random"
@@ -1459,6 +1467,7 @@
     "safe_mode"
     "samsungtv"
     "scene"
+    "scrape"
     "screenlogic"
     "script"
     "search"
@@ -1476,6 +1485,7 @@
     "sia"
     "sigfox"
     "sighthound"
+    "signal_messenger"
     "simplisafe"
     "simulated"
     "siren"
@@ -1604,6 +1614,7 @@
     "whois"
     "wiffi"
     "wilight"
+    "wiz"
     "wled"
     "workday"
     "worldclock"
diff --git a/nixpkgs/pkgs/servers/home-assistant/default.nix b/nixpkgs/pkgs/servers/home-assistant/default.nix
index 920343de67b6..b6ceb02270ae 100644
--- a/nixpkgs/pkgs/servers/home-assistant/default.nix
+++ b/nixpkgs/pkgs/servers/home-assistant/default.nix
@@ -29,7 +29,27 @@
 let
   defaultOverrides = [
     # Override the version of some packages pinned in Home Assistant's setup.py and requirements_all.txt
-    (mkOverride "python-slugify" "4.0.1" "69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270")
+    (mkOverride "python-slugify" "4.0.1" "sha256-aaUXdm4AwSaOW7/A0BCgqFCN4LGNMK1aH/NX+K5yQnA=")
+
+    # pytest-aiohttp>0.3.0 breaks home-assistant tests
+    (self: super: {
+      pytest-aiohttp = super.pytest-aiohttp.overridePythonAttrs (oldAttrs: rec {
+        version = "0.3.0";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "0kx4mbs9bflycd8x9af0idcjhdgnzri3nw1qb0vpfyb3751qaaf9";
+        };
+      });
+      aiohomekit = super.aiohomekit.overridePythonAttrs (oldAttrs: {
+        doCheck = false; # requires aiohttp>=1.0.0
+      });
+      hass-nabucasa = super.hass-nabucasa.overridePythonAttrs (oldAttrs: {
+        doCheck = false; # requires aiohttp>=1.0.0
+      });
+      zwave-js-server-python = super.zwave-js-server-python.overridePythonAttrs (oldAttrs: {
+        doCheck = false; # requires aiohttp>=1.0.0
+      });
+    })
 
     (self: super: {
       huawei-lte-api = super.huawei-lte-api.overridePythonAttrs (oldAttrs: rec {
@@ -58,7 +78,7 @@ let
     })
 
     # Pinned due to API changes in 0.1.0
-    (mkOverride "poolsense" "0.0.8" "09y4fq0gdvgkfsykpxnvmfv92dpbknnq5v82spz43ak6hjnhgcyp")
+    (mkOverride "poolsense" "0.0.8" "sha256-17MHrYRmqkH+1QLtgq2d6zaRtqvb9ju9dvPt9gB2xCc=")
 
     # Pinned due to API changes >0.3.5.3
     (self: super: {
@@ -105,12 +125,12 @@ let
     })
   ];
 
-  mkOverride = attrName: version: sha256:
+  mkOverride = attrName: version: hash:
     self: super: {
       ${attrName} = super.${attrName}.overridePythonAttrs (oldAttrs: {
         inherit version;
         src = oldAttrs.src.override {
-          inherit version sha256;
+          inherit version hash;
         };
       });
     };
@@ -138,7 +158,7 @@ let
   extraPackagesFile = writeText "home-assistant-packages" (lib.concatMapStringsSep "\n" (pkg: pkg.pname) extraBuildInputs);
 
   # Don't forget to run parse-requirements.py after updating
-  hassVersion = "2022.2.9";
+  hassVersion = "2022.3.4";
 
 in python.pkgs.buildPythonApplication rec {
   pname = "homeassistant";
@@ -156,7 +176,7 @@ in python.pkgs.buildPythonApplication rec {
     owner = "home-assistant";
     repo = "core";
     rev = version;
-    hash = "sha256-So/MAKyFVa1TchrVE4ego1fRbgOXCoXR3w/rJLFSBqI=";
+    hash = "sha256-7de1m7pvPkgCcZN/Slhy26Y1j2NtkebkGanSTl9jN1M=";
   };
 
   # leave this in, so users don't have to constantly update their downstream patch handling
@@ -217,6 +237,8 @@ in python.pkgs.buildPythonApplication rec {
     yarl
     # Not in setup.py, but used in homeassistant/util/package.py
     setuptools
+    # Not in setup.py, but uncounditionally imported via tests/conftest.py
+    paho-mqtt
   ] ++ componentBuildInputs ++ extraBuildInputs;
 
   makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip";
diff --git a/nixpkgs/pkgs/servers/home-assistant/frontend.nix b/nixpkgs/pkgs/servers/home-assistant/frontend.nix
index 2aabb0d9312c..9bfa5cf2f37a 100644
--- a/nixpkgs/pkgs/servers/home-assistant/frontend.nix
+++ b/nixpkgs/pkgs/servers/home-assistant/frontend.nix
@@ -4,7 +4,7 @@ buildPythonPackage rec {
   # the frontend version corresponding to a specific home-assistant version can be found here
   # https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/frontend/manifest.json
   pname = "home-assistant-frontend";
-  version = "20220203.1";
+  version = "20220301.1";
   format = "wheel";
 
   src = fetchPypi {
@@ -12,7 +12,7 @@ buildPythonPackage rec {
     pname = "home_assistant_frontend";
     dist = "py3";
     python = "py3";
-    sha256 = "sha256-6+TzBhHo9+eo6Hlk8RF+BAt4O0i759iAN+dKAPDmTNY=";
+    sha256 = "sha256-+S888lUHbWqEJQm5HvZqimTfqoDEHYRVAoGQ5UvU4u4=";
   };
 
   # there is nothing to strip in this package
diff --git a/nixpkgs/pkgs/servers/home-assistant/parse-requirements.py b/nixpkgs/pkgs/servers/home-assistant/parse-requirements.py
index fbe46b237787..0e3d5d5553e7 100755
--- a/nixpkgs/pkgs/servers/home-assistant/parse-requirements.py
+++ b/nixpkgs/pkgs/servers/home-assistant/parse-requirements.py
@@ -34,16 +34,12 @@ from rich.table import Table
 COMPONENT_PREFIX = "homeassistant.components"
 PKG_SET = "home-assistant.python.pkgs"
 
-# If some requirements are matched by multiple Python packages,
-# the following can be used to choose one of them
+# If some requirements are matched by multiple or no Python packages, the
+# following can be used to choose the correct one
 PKG_PREFERENCES = {
-    # Use python3Packages.youtube-dl-light instead of python3Packages.youtube-dl
-    "youtube-dl": "youtube-dl-light",
-    "tensorflow-bin": "tensorflow",
-    "tensorflow-bin_2": "tensorflow",
-    "tensorflowWithoutCuda": "tensorflow",
-    "tensorflow-build_2": "tensorflow",
-    "whois": "python-whois",
+    "youtube_dl": "youtube-dl-light",
+    "tensorflow": "tensorflow",
+    "fiblary3": "fiblary3-fork", # https://github.com/home-assistant/core/issues/66466
 }
 
 
@@ -120,39 +116,28 @@ def dump_packages() -> Dict[str, Dict[str, str]]:
 
 
 def name_to_attr_path(req: str, packages: Dict[str, Dict[str, str]]) -> Optional[str]:
-    attr_paths = set()
+    if req in PKG_PREFERENCES:
+        return f"{PKG_SET}.{PKG_PREFERENCES[req]}"
+    attr_paths = []
     names = [req]
     # E.g. python-mpd2 is actually called python3.6-mpd2
     # instead of python-3.6-python-mpd2 inside Nixpkgs
     if req.startswith("python-") or req.startswith("python_"):
         names.append(req[len("python-") :])
-    # Add name variant without extra_require, e.g. samsungctl
-    # instead of samsungctl[websocket]
-    if req.endswith("]"):
-        names.append(req[:req.find("[")])
     for name in names:
         # treat "-" and "_" equally
         name = re.sub("[-_]", "[-_]", name)
         # python(minor).(major)-(pname)-(version or unstable-date)
         # we need the version qualifier, or we'll have multiple matches
         # (e.g. pyserial and pyserial-asyncio when looking for pyserial)
-        pattern = re.compile("^python\\d\\.\\d-{}-(?:\\d|unstable-.*)".format(name), re.I)
+        pattern = re.compile(f"^python\\d\\.\\d-{name}-(?:\\d|unstable-.*)", re.I)
         for attr_path, package in packages.items():
             if pattern.match(package["name"]):
-                attr_paths.add(attr_path)
-    if len(attr_paths) > 1:
-        for to_replace, replacement in PKG_PREFERENCES.items():
-            try:
-                attr_paths.remove(PKG_SET + "." + to_replace)
-                attr_paths.add(PKG_SET + "." + replacement)
-            except KeyError:
-                pass
+                attr_paths.append(attr_path)
     # Let's hope there's only one derivation with a matching name
-    assert len(attr_paths) <= 1, "{} matches more than one derivation: {}".format(
-        req, attr_paths
-    )
-    if len(attr_paths) == 1:
-        return attr_paths.pop()
+    assert len(attr_paths) <= 1, f"{req} matches more than one derivation: {attr_paths}"
+    if attr_paths:
+        return attr_paths[0]
     else:
         return None
 
@@ -180,6 +165,10 @@ def main() -> None:
             # Therefore, if there's a "#" in the line, only take the part after it
             req = req[req.find("#") + 1 :]
             name, required_version = req.split("==", maxsplit=1)
+            # Remove extra_require from name, e.g. samsungctl instead of
+            # samsungctl[websocket]
+            if name.endswith("]"):
+                name = name[:name.find("[")]
             attr_path = name_to_attr_path(name, packages)
             if our_version := get_pkg_version(name, packages):
                 if Version.parse(our_version) < Version.parse(required_version):
diff --git a/nixpkgs/pkgs/servers/home-assistant/tests.nix b/nixpkgs/pkgs/servers/home-assistant/tests.nix
index 31dbe64725ce..ae2d91b933f9 100644
--- a/nixpkgs/pkgs/servers/home-assistant/tests.nix
+++ b/nixpkgs/pkgs/servers/home-assistant/tests.nix
@@ -11,8 +11,9 @@ let
     config = [ pydispatcher ];
     generic = [ ha-av ];
     google_translate = [ mutagen ];
+    lovelace = [ PyChromecast ];
     nest = [ ha-av ];
-    onboarding = [ pymetno rpi-bad-power ];
+    onboarding = [ pymetno radios rpi-bad-power ];
     version = [ aioaseko ];
     voicerss = [ mutagen ];
     yandextts = [ mutagen ];
@@ -28,6 +29,13 @@ let
     ];
   };
 
+  extraDisabledTests = {
+    roku = [
+      # homeassistant.components.roku.media_player:media_player.py:428 Media type music is not supported with format None (mime: audio/x-matroska)
+      "test_services_play_media_audio"
+    ];
+  };
+
   extraPytestFlagsArray = {
     asuswrt = [
       # asuswrt/test_config_flow.py: Sandbox network limitations, fails with unexpected error
@@ -45,6 +53,7 @@ in lib.listToAttrs (map (component: lib.nameValuePair component (
       ++ home-assistant.getPackages component home-assistant.python.pkgs
       ++ extraCheckInputs.${component} or [ ];
 
+    disabledTests = old.disabledTests ++ extraDisabledTests.${component} or [];
     disabledTestPaths = old.disabledTestPaths ++ extraDisabledTestPaths.${component} or [ ];
 
     pytestFlagsArray = lib.remove "tests" old.pytestFlagsArray
@@ -59,6 +68,7 @@ in lib.listToAttrs (map (component: lib.nameValuePair component (
       broken = lib.elem component [
         "airtouch4"
         "dnsip"
+        "zwave"
       ];
       # upstream only tests on Linux, so do we.
       platforms = lib.platforms.linux;