diff options
Diffstat (limited to 'pkgs/servers/home-assistant')
-rw-r--r-- | pkgs/servers/home-assistant/component-packages.nix | 683 | ||||
-rw-r--r-- | pkgs/servers/home-assistant/default.nix | 857 | ||||
-rw-r--r-- | pkgs/servers/home-assistant/frontend.nix | 10 | ||||
-rwxr-xr-x | pkgs/servers/home-assistant/parse-requirements.py | 22 | ||||
-rw-r--r-- | pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch | 27 | ||||
-rw-r--r-- | pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch | 4 | ||||
-rw-r--r-- | pkgs/servers/home-assistant/tests.nix | 67 |
7 files changed, 814 insertions, 856 deletions
diff --git a/pkgs/servers/home-assistant/component-packages.nix b/pkgs/servers/home-assistant/component-packages.nix index 454b54886a88d..714087eb2e602 100644 --- a/pkgs/servers/home-assistant/component-packages.nix +++ b/pkgs/servers/home-assistant/component-packages.nix @@ -2,14 +2,14 @@ # Do not edit! { - version = "2021.12.7"; + version = "2022.2.9"; components = { "abode" = ps: with ps; [ abodepy ]; "accuweather" = ps: with ps; [ accuweather ]; "acer_projector" = ps: with ps; [ pyserial ]; "acmeda" = ps: with ps; [ aiopulse ]; "actiontec" = ps: with ps; [ ]; - "adax" = ps: with ps; [ adax ]; + "adax" = ps: with ps; [ adax-local adax ]; "adguard" = ps: with ps; [ adguardhome ]; "ads" = ps: with ps; [ pyads ]; "advantage_air" = ps: with ps; [ advantage-air ]; @@ -45,27 +45,28 @@ "apcupsd" = ps: with ps; [ apcaccess ]; "api" = ps: with ps; [ aiohttp-cors ]; "apns" = ps: with ps; [ ]; # missing inputs: apns2 - "apple_tv" = ps: with ps; [ pyatv ]; + "apple_tv" = ps: with ps; [ aiohttp-cors ifaddr pyatv zeroconf ]; "apprise" = ps: with ps; [ apprise ]; "aprs" = ps: with ps; [ aprslib geopy ]; "aqualogic" = ps: with ps; [ aqualogic ]; "aquostv" = ps: with ps; [ ]; # missing inputs: sharp_aquos_rc "arcam_fmj" = ps: with ps; [ arcam-fmj ]; - "arduino" = ps: with ps; [ ]; # missing inputs: PyMata "arest" = ps: with ps; [ ]; "arlo" = ps: with ps; [ ha-ffmpeg pyarlo ]; "arris_tg2492lg" = ps: with ps; [ ]; # missing inputs: arris-tg2492lg "aruba" = ps: with ps; [ pexpect ]; "arwn" = ps: with ps; [ aiohttp-cors paho-mqtt ]; - "asterisk_cdr" = ps: with ps; [ ]; # missing inputs: asterisk_mbox - "asterisk_mbox" = ps: with ps; [ ]; # missing inputs: asterisk_mbox + "aseko_pool_live" = ps: with ps; [ aioaseko ]; + "asterisk_cdr" = ps: with ps; [ asterisk-mbox ]; + "asterisk_mbox" = ps: with ps; [ asterisk-mbox ]; "asuswrt" = ps: with ps; [ aioasuswrt ]; "atag" = ps: with ps; [ pyatag ]; "aten_pe" = ps: with ps; [ atenpdu ]; "atome" = ps: with ps; [ pyatome ]; "august" = ps: with ps; [ yalexs ]; "aurora" = ps: with ps; [ auroranoaa ]; - "aurora_abb_powerone" = ps: with ps; [ ]; # missing inputs: aurorapy + "aurora_abb_powerone" = ps: with ps; [ aurorapy ]; + "aussie_broadband" = ps: with ps; [ pyaussiebb ]; "auth" = ps: with ps; [ aiohttp-cors ]; "automation" = ps: with ps; [ aiohttp-cors ]; "avea" = ps: with ps; [ avea ]; @@ -82,7 +83,7 @@ "bbb_gpio" = ps: with ps; [ ]; # missing inputs: Adafruit_BBIO "bbox" = ps: with ps; [ ]; # missing inputs: pybbox "beewi_smartclim" = ps: with ps; [ ]; # missing inputs: beewi_smartclim - "bh1750" = ps: with ps; [ smbus-cffi ]; # missing inputs: i2csense + "bh1750" = ps: with ps; [ i2csense smbus-cffi ]; "binary_sensor" = ps: with ps; [ ]; "bitcoin" = ps: with ps; [ blockchain ]; "bizkaibus" = ps: with ps; [ bizkaibus ]; @@ -97,7 +98,7 @@ "bluesound" = ps: with ps; [ xmltodict ]; "bluetooth_le_tracker" = ps: with ps; [ pygatt ]; "bluetooth_tracker" = ps: with ps; [ bt-proximity pybluez ]; - "bme280" = ps: with ps; [ smbus-cffi ]; # missing inputs: bme280spi i2csense + "bme280" = ps: with ps; [ bme280spi i2csense smbus-cffi ]; "bme680" = ps: with ps; [ bme680 smbus-cffi ]; "bmp280" = ps: with ps; [ ]; # missing inputs: RPi.GPIO adafruit-circuitpython-bmp280 "bmw_connected_drive" = ps: with ps; [ bimmer-connected ]; @@ -121,7 +122,7 @@ "cast" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa ifaddr mutagen plexapi plexauth plexwebsocket PyChromecast zeroconf ]; "cert_expiry" = ps: with ps; [ ]; "channels" = ps: with ps; [ pychannels ]; - "circuit" = ps: with ps; [ ]; # missing inputs: circuit-webhook + "circuit" = ps: with ps; [ circuit-webhook ]; "cisco_ios" = ps: with ps; [ pexpect ]; "cisco_mobility_express" = ps: with ps; [ ciscomobilityexpress ]; "cisco_webex_teams" = ps: with ps; [ webexteamssdk ]; @@ -135,7 +136,7 @@ "cloud" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa ]; "cloudflare" = ps: with ps; [ pycfdns ]; "cmus" = ps: with ps; [ ]; # missing inputs: pycmus - "co2signal" = ps: with ps; [ ]; # missing inputs: co2signal + "co2signal" = ps: with ps; [ co2signal ]; "coinbase" = ps: with ps; [ ]; # missing inputs: coinbase "color_extractor" = ps: with ps; [ colorthief ]; "comed_hourly_pricing" = ps: with ps; [ ]; @@ -181,6 +182,7 @@ "dexcom" = ps: with ps; [ pydexcom ]; "dhcp" = ps: with ps; [ aiodiscover scapy ]; "dht" = ps: with ps; [ ]; # missing inputs: RPi.GPIO adafruit-circuitpython-dht + "diagnostics" = ps: with ps; [ aiohttp-cors ]; "dialogflow" = ps: with ps; [ aiohttp-cors ]; "digital_ocean" = ps: with ps; [ digital-ocean ]; "digitalloggers" = ps: with ps; [ ]; # missing inputs: dlipower @@ -206,7 +208,7 @@ "dunehd" = ps: with ps; [ pdunehd ]; "dwd_weather_warnings" = ps: with ps; [ dwdwfsapi ]; "dweet" = ps: with ps; [ ]; # missing inputs: dweepy - "dynalite" = ps: with ps; [ ]; # missing inputs: dynalite_devices + "dynalite" = ps: with ps; [ dynalite-devices ]; "eafm" = ps: with ps; [ aioeafm ]; "ebox" = ps: with ps; [ ]; # missing inputs: pyebox "ebusd" = ps: with ps; [ ]; # missing inputs: ebusdpy @@ -217,13 +219,13 @@ "eddystone_temperature" = ps: with ps; [ construct ]; # missing inputs: beacontools[scan] "edimax" = ps: with ps; [ pyedimax ]; "edl21" = ps: with ps; [ pysml ]; - "ee_brightbox" = ps: with ps; [ eebrightbox ]; "efergy" = ps: with ps; [ pyefergy ]; "egardia" = ps: with ps; [ pythonegardia ]; "eight_sleep" = ps: with ps; [ pyeight ]; "elgato" = ps: with ps; [ elgato ]; "eliqonline" = ps: with ps; [ eliqonline ]; "elkm1" = ps: with ps; [ elkm1-lib ]; + "elmax" = ps: with ps; [ elmax-api ]; "elv" = ps: with ps; [ pypca ]; "emby" = ps: with ps; [ pyemby ]; "emoncms" = ps: with ps; [ ]; @@ -283,7 +285,7 @@ "flume" = ps: with ps; [ pyflume ]; "flunearyou" = ps: with ps; [ pyflunearyou ]; "flux" = ps: with ps; [ ]; - "flux_led" = ps: with ps; [ flux-led ]; + "flux_led" = ps: with ps; [ aiohttp-cors flux-led ifaddr ]; "folder" = ps: with ps; [ ]; "folder_watcher" = ps: with ps; [ watchdog ]; "foobot" = ps: with ps; [ foobot-async ]; @@ -310,7 +312,7 @@ "generic" = ps: with ps; [ ]; "generic_hygrostat" = ps: with ps; [ ]; "generic_thermostat" = ps: with ps; [ sqlalchemy ]; - "geniushub" = ps: with ps; [ ]; # missing inputs: geniushub-client + "geniushub" = ps: with ps; [ geniushub-client ]; "geo_json_events" = ps: with ps; [ geojson-client ]; "geo_location" = ps: with ps; [ ]; "geo_rss_events" = ps: with ps; [ georss-generic-client ]; @@ -326,6 +328,7 @@ "goalfeed" = ps: with ps; [ ]; # missing inputs: pysher "goalzero" = ps: with ps; [ goalzero ]; "gogogate2" = ps: with ps; [ ismartgate ]; + "goodwe" = ps: with ps; [ goodwe ]; "google" = ps: with ps; [ google-api-python-client httplib2 oauth2client ]; "google_assistant" = ps: with ps; [ pyturbojpeg aiohttp-cors ]; "google_cloud" = ps: with ps; [ google-cloud-texttospeech ]; @@ -335,7 +338,6 @@ "google_translate" = ps: with ps; [ gtts ]; "google_travel_time" = ps: with ps; [ googlemaps ]; "google_wifi" = ps: with ps; [ ]; - "gpmdp" = ps: with ps; [ websocket-client ]; "gpsd" = ps: with ps; [ gps3 ]; "gpslogger" = ps: with ps; [ aiohttp-cors ]; "graphite" = ps: with ps; [ ]; @@ -373,13 +375,14 @@ "homekit_controller" = ps: with ps; [ aiohomekit aiohttp-cors ifaddr zeroconf ]; "homematic" = ps: with ps; [ pyhomematic ]; "homematicip_cloud" = ps: with ps; [ homematicip ]; + "homewizard" = ps: with ps; [ aiohwenergy ]; "homeworks" = ps: with ps; [ pyhomeworks ]; "honeywell" = ps: with ps; [ somecomfort ]; "horizon" = ps: with ps; [ ]; # missing inputs: horimote "hp_ilo" = ps: with ps; [ python-hpilo ]; "html5" = ps: with ps; [ aiohttp-cors pywebpush ]; "http" = ps: with ps; [ aiohttp-cors ]; - "htu21d" = ps: with ps; [ smbus-cffi ]; # missing inputs: i2csense + "htu21d" = ps: with ps; [ i2csense smbus-cffi ]; "huawei_lte" = ps: with ps; [ huawei-lte-api stringcase url-normalize ]; "hue" = ps: with ps; [ aiohue ]; "huisbaasje" = ps: with ps; [ huisbaasje-client ]; @@ -404,12 +407,14 @@ "incomfort" = ps: with ps; [ incomfort-client ]; "influxdb" = ps: with ps; [ influxdb-client influxdb ]; "input_boolean" = ps: with ps; [ ]; + "input_button" = ps: with ps; [ ]; "input_datetime" = ps: with ps; [ ]; "input_number" = ps: with ps; [ ]; "input_select" = ps: with ps; [ ]; "input_text" = ps: with ps; [ ]; "insteon" = ps: with ps; [ pyinsteon ]; "integration" = ps: with ps; [ ]; + "intellifire" = ps: with ps; [ intellifire4py ]; "intent" = ps: with ps; [ aiohttp-cors ]; "intent_script" = ps: with ps; [ ]; "intesishome" = ps: with ps; [ pyintesishome ]; @@ -454,12 +459,12 @@ "launch_library" = ps: with ps; [ pylaunches ]; "lcn" = ps: with ps; [ pypck ]; "lg_netcast" = ps: with ps; [ pylgnetcast ]; - "lg_soundbar" = ps: with ps; [ ]; # missing inputs: temescal + "lg_soundbar" = ps: with ps; [ temescal ]; "life360" = ps: with ps; [ life360 ]; "lifx" = ps: with ps; [ aiolifx aiolifx-effects ]; "lifx_cloud" = ps: with ps; [ ]; "light" = ps: with ps; [ ]; - "lightwave" = ps: with ps; [ ]; # missing inputs: lightwave + "lightwave" = ps: with ps; [ lightwave ]; "limitlessled" = ps: with ps; [ limitlessled ]; "linksys_smart" = ps: with ps; [ ]; "linode" = ps: with ps; [ linode-api ]; @@ -484,7 +489,7 @@ "luftdaten" = ps: with ps; [ luftdaten ]; "lupusec" = ps: with ps; [ lupupy ]; "lutron" = ps: with ps; [ pylutron ]; - "lutron_caseta" = ps: with ps; [ aiolip pylutron-caseta ]; + "lutron_caseta" = ps: with ps; [ pylutron-caseta ]; "lw12wifi" = ps: with ps; [ ]; # missing inputs: lw12 "lyric" = ps: with ps; [ aiohttp-cors aiolyric ]; "magicseaweed" = ps: with ps; [ ]; # missing inputs: magicseaweed @@ -503,7 +508,7 @@ "media_player" = ps: with ps; [ aiohttp-cors ]; "media_source" = ps: with ps; [ aiohttp-cors ]; "mediaroom" = ps: with ps; [ pymediaroom ]; - "melcloud" = ps: with ps; [ ]; # missing inputs: pymelcloud + "melcloud" = ps: with ps; [ pymelcloud ]; "melissa" = ps: with ps; [ ]; # missing inputs: py-melissa-climate "meraki" = ps: with ps; [ aiohttp-cors ]; "message_bird" = ps: with ps; [ ]; # missing inputs: messagebird @@ -564,7 +569,7 @@ "nest" = ps: with ps; [ aiohttp-cors google-nest-sdm ha-ffmpeg python-nest ]; "netatmo" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa pyatmo ]; "netdata" = ps: with ps; [ netdata ]; - "netgear" = ps: with ps; [ ]; # missing inputs: pynetgear + "netgear" = ps: with ps; [ pynetgear ]; "netgear_lte" = ps: with ps; [ eternalegypt ]; "netio" = ps: with ps; [ aiohttp-cors ]; # missing inputs: pynetio "network" = ps: with ps; [ aiohttp-cors ifaddr ]; @@ -576,6 +581,7 @@ "nightscout" = ps: with ps; [ py-nightscout ]; "niko_home_control" = ps: with ps; [ niko-home-control ]; "nilu" = ps: with ps; [ niluclient ]; + "nina" = ps: with ps; [ pynina ]; "nissan_leaf" = ps: with ps; [ pycarwings2 ]; "nmap_tracker" = ps: with ps; [ aiohttp-cors getmac ifaddr netmap ]; # missing inputs: mac-vendor-lookup "nmbs" = ps: with ps; [ ]; # missing inputs: pyrail @@ -591,7 +597,7 @@ "nuki" = ps: with ps; [ pynuki ]; "numato" = ps: with ps; [ ]; # missing inputs: numato-gpio "number" = ps: with ps; [ ]; - "nut" = ps: with ps; [ ]; # missing inputs: pynut2 + "nut" = ps: with ps; [ pynut2 ]; "nws" = ps: with ps; [ pynws ]; "nx584" = ps: with ps; [ pynx584 ]; "nzbget" = ps: with ps; [ ]; # missing inputs: pynzbgetapi @@ -603,15 +609,17 @@ "ombi" = ps: with ps; [ pyombi ]; "omnilogic" = ps: with ps; [ omnilogic ]; "onboarding" = ps: with ps; [ aiohttp-cors home-assistant-frontend pillow sqlalchemy ]; + "oncue" = ps: with ps; [ aiooncue ]; "ondilo_ico" = ps: with ps; [ aiohttp-cors ondilo ]; - "onewire" = ps: with ps; [ ]; # missing inputs: pi1wire pyownet + "onewire" = ps: with ps; [ pi1wire pyownet ]; "onkyo" = ps: with ps; [ onkyo-eiscp ]; - "onvif" = ps: with ps; [ ha-ffmpeg ]; # missing inputs: WSDiscovery onvif-zeep-async + "onvif" = ps: with ps; [ wsdiscovery ha-ffmpeg onvif-zeep-async ]; + "open_meteo" = ps: with ps; [ open-meteo ]; "openalpr_cloud" = ps: with ps; [ ]; "openalpr_local" = ps: with ps; [ ]; "opencv" = ps: with ps; [ numpy ]; # missing inputs: opencv-python-headless "openerz" = ps: with ps; [ openerz-api ]; - "openevse" = ps: with ps; [ ]; # missing inputs: openevsewifi + "openevse" = ps: with ps; [ openevsewifi ]; "openexchangerates" = ps: with ps; [ ]; "opengarage" = ps: with ps; [ open-garage ]; "openhardwaremonitor" = ps: with ps; [ ]; @@ -628,6 +636,7 @@ "orvibo" = ps: with ps; [ orvibo ]; "osramlightify" = ps: with ps; [ ]; # missing inputs: lightify "otp" = ps: with ps; [ pyotp ]; + "overkiz" = ps: with ps; [ pyoverkiz ]; "ovo_energy" = ps: with ps; [ ovoenergy ]; "owntracks" = ps: with ps; [ pynacl pyturbojpeg aiohttp-cors hass-nabucasa paho-mqtt ]; "ozw" = ps: with ps; [ aiohttp-cors paho-mqtt python-openzwave-mqtt ]; @@ -675,7 +684,7 @@ "pushbullet" = ps: with ps; [ pushbullet ]; "pushover" = ps: with ps; [ pushover-complete ]; "pushsafer" = ps: with ps; [ ]; - "pvoutput" = ps: with ps; [ jsonpath xmltodict ]; + "pvoutput" = ps: with ps; [ pvo ]; "pvpc_hourly_pricing" = ps: with ps; [ aiopvpc ]; "pyload" = ps: with ps; [ ]; "python_script" = ps: with ps; [ restrictedpython ]; @@ -684,7 +693,7 @@ "qnap" = ps: with ps; [ ]; # missing inputs: qnapstats "qrcode" = ps: with ps; [ pillow ]; # missing inputs: pyzbar "quantum_gateway" = ps: with ps; [ quantum-gateway ]; - "qvr_pro" = ps: with ps; [ ]; # missing inputs: pyqvrpro + "qvr_pro" = ps: with ps; [ pyqvrpro ]; "qwikswitch" = ps: with ps; [ ]; # missing inputs: pyqwikswitch "rachio" = ps: with ps; [ pyturbojpeg aiohttp-cors hass-nabucasa rachiopy ]; "radarr" = ps: with ps; [ ]; @@ -727,10 +736,11 @@ "rpi_gpio" = ps: with ps; [ ]; # missing inputs: RPi.GPIO "rpi_gpio_pwm" = ps: with ps; [ ]; # missing inputs: pwmled "rpi_pfio" = ps: with ps; [ ]; # missing inputs: pifacecommon pifacedigitalio - "rpi_power" = ps: with ps; [ ]; # missing inputs: rpi-bad-power + "rpi_power" = ps: with ps; [ rpi-bad-power ]; "rpi_rf" = ps: with ps; [ ]; # missing inputs: RPi.GPIO rpi-rf "rss_feed_template" = ps: with ps; [ aiohttp-cors ]; "rtorrent" = ps: with ps; [ ]; + "rtsp_to_webrtc" = ps: with ps; [ pyturbojpeg aiohttp-cors rtsp-to-webrtc ]; "ruckus_unleashed" = ps: with ps; [ pyruckus ]; "russound_rio" = ps: with ps; [ ]; # missing inputs: russound_rio "russound_rnet" = ps: with ps; [ ]; # missing inputs: russound @@ -751,6 +761,7 @@ "sendgrid" = ps: with ps; [ sendgrid ]; "sense" = ps: with ps; [ sense-energy ]; "sensehat" = ps: with ps; [ ]; # missing inputs: sense-hat + "senseme" = ps: with ps; [ aiosenseme ]; "sensibo" = ps: with ps; [ ]; # missing inputs: pysensibo "sensor" = ps: with ps; [ sqlalchemy ]; "sentry" = ps: with ps; [ sentry-sdk ]; @@ -805,7 +816,7 @@ "somfy_mylink" = ps: with ps; [ somfy-mylink-synergy ]; "sonarr" = ps: with ps; [ sonarr ]; "songpal" = ps: with ps; [ python-songpal ]; - "sonos" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr plexapi plexauth plexwebsocket soco zeroconf ]; + "sonos" = ps: with ps; [ aiohttp-cors async-upnp-client ifaddr plexapi plexauth plexwebsocket soco spotipy zeroconf ]; "sony_projector" = ps: with ps; [ pysdcp ]; "soundtouch" = ps: with ps; [ aiohttp-cors ifaddr libsoundtouch zeroconf ]; "spaceapi" = ps: with ps; [ aiohttp-cors ]; @@ -824,9 +835,10 @@ "statistics" = ps: with ps; [ sqlalchemy ]; "statsd" = ps: with ps; [ statsd ]; "steam_online" = ps: with ps; [ ]; # missing inputs: steamodd + "steamist" = ps: with ps; [ aiohttp-cors aiosteamist discovery30303 ifaddr ]; "stiebel_eltron" = ps: with ps; [ pymodbus ]; # missing inputs: pystiebeleltron "stookalert" = ps: with ps; [ ]; # missing inputs: stookalert - "stream" = ps: with ps; [ aiohttp-cors ha-av ]; + "stream" = ps: with ps; [ pyturbojpeg aiohttp-cors av ]; "streamlabswater" = ps: with ps; [ streamlabswater ]; "stt" = ps: with ps; [ aiohttp-cors ]; "subaru" = ps: with ps; [ subarulink ]; @@ -850,11 +862,10 @@ "syslog" = ps: with ps; [ ]; "system_bridge" = ps: with ps; [ aiohttp-cors ifaddr systembridge zeroconf ]; "system_health" = ps: with ps; [ aiohttp-cors ]; - "system_log" = ps: with ps; [ aiohttp-cors ]; + "system_log" = ps: with ps; [ ]; "systemmonitor" = ps: with ps; [ psutil ]; "tado" = ps: with ps; [ python-tado ]; "tag" = ps: with ps; [ ]; - "tahoma" = ps: with ps; [ tahoma-api ]; "tailscale" = ps: with ps; [ tailscale ]; "tank_utility" = ps: with ps; [ ]; # missing inputs: tank_utility "tankerkoenig" = ps: with ps; [ pytankerkoenig ]; @@ -879,7 +890,7 @@ "thinkingcleaner" = ps: with ps; [ ]; # missing inputs: pythinkingcleaner "thomson" = ps: with ps; [ ]; "threshold" = ps: with ps; [ ]; - "tibber" = ps: with ps; [ pytibber ]; + "tibber" = ps: with ps; [ pytibber sqlalchemy ]; "tikteck" = ps: with ps; [ ]; # missing inputs: tikteck "tile" = ps: with ps; [ pytile ]; "time_date" = ps: with ps; [ ]; @@ -912,7 +923,7 @@ "twilio" = ps: with ps; [ aiohttp-cors twilio ]; "twilio_call" = ps: with ps; [ aiohttp-cors twilio ]; "twilio_sms" = ps: with ps; [ aiohttp-cors twilio ]; - "twinkly" = ps: with ps; [ twinkly-client ]; + "twinkly" = ps: with ps; [ ttls ]; "twitch" = ps: with ps; [ python-twitch-client ]; "twitter" = ps: with ps; [ twitterapi ]; "ubus" = ps: with ps; [ openwrt-ubus-rpc ]; @@ -921,6 +932,7 @@ "unifi" = ps: with ps; [ aiounifi ]; "unifi_direct" = ps: with ps; [ pexpect ]; "unifiled" = ps: with ps; [ unifiled ]; + "unifiprotect" = ps: with ps; [ aiohttp-cors ]; # missing inputs: pyunifiprotect unifi-discovery "universal" = ps: with ps; [ ]; "upb" = ps: with ps; [ upb-lib ]; "upc_connect" = ps: with ps; [ connect-box ]; @@ -937,7 +949,7 @@ "vacuum" = ps: with ps; [ ]; "vallox" = ps: with ps; [ ]; # missing inputs: vallox-websocket-api "vasttrafik" = ps: with ps; [ ]; # missing inputs: vtjp - "velbus" = ps: with ps; [ velbus-aio ]; + "velbus" = ps: with ps; [ aiohttp-cors pyserial pyudev velbus-aio ]; "velux" = ps: with ps; [ pyvlx ]; "venstar" = ps: with ps; [ venstarcolortouch ]; "vera" = ps: with ps; [ pyvera ]; @@ -969,11 +981,11 @@ "waze_travel_time" = ps: with ps; [ wazeroutecalculator ]; "weather" = ps: with ps; [ ]; "webhook" = ps: with ps; [ aiohttp-cors ]; - "webostv" = ps: with ps; [ aiopylgtv ]; + "webostv" = ps: with ps; [ aiowebostv sqlalchemy ]; "websocket_api" = ps: with ps; [ aiohttp-cors ]; "wemo" = ps: with ps; [ pywemo ]; "whirlpool" = ps: with ps; [ whirlpool-sixth-sense ]; - "whois" = ps: with ps; [ python-whois ]; + "whois" = ps: with ps; [ whois ]; "wiffi" = ps: with ps; [ wiffi ]; "wilight" = ps: with ps; [ pywilight ]; "wirelesstag" = ps: with ps; [ ]; # missing inputs: wirelesstagpy @@ -1020,4 +1032,599 @@ "zwave" = ps: with ps; [ homeassistant-pyozw pydispatcher ]; "zwave_js" = ps: with ps; [ aiohttp-cors pyserial pyudev zwave-js-server-python ]; }; + # components listed in tests/components for which all dependencies are packaged + supportedComponentsWithTests = [ + "abode" + "accuweather" + "acmeda" + "adax" + "adguard" + "advantage_air" + "aemet" + "agent_dvr" + "air_quality" + "airly" + "airnow" + "airthings" + "airtouch4" + "airvisual" + "alarm_control_panel" + "alarmdecoder" + "alert" + "alexa" + "almond" + "ambee" + "amberelectric" + "ambiclimate" + "ambient_station" + "analytics" + "androidtv" + "apache_kafka" + "api" + "apple_tv" + "apprise" + "aprs" + "arcam_fmj" + "arlo" + "aseko_pool_live" + "asuswrt" + "atag" + "august" + "aurora" + "aurora_abb_powerone" + "aussie_broadband" + "auth" + "automation" + "awair" + "aws" + "axis" + "azure_devops" + "azure_event_hub" + "balboa" + "bayesian" + "binary_sensor" + "blackbird" + "blebox" + "blink" + "blueprint" + "bluetooth_le_tracker" + "bmw_connected_drive" + "bond" + "bosch_shc" + "braviatv" + "broadlink" + "brother" + "bsblan" + "buienradar" + "button" + "caldav" + "calendar" + "camera" + "canary" + "cast" + "cert_expiry" + "climacell" + "climate" + "cloud" + "cloudflare" + "co2signal" + "color_extractor" + "comfoconnect" + "command_line" + "compensation" + "config" + "configurator" + "control4" + "conversation" + "coolmaster" + "coronavirus" + "counter" + "cover" + "cpuspeed" + "crownstone" + "daikin" + "darksky" + "datadog" + "debugpy" + "deconz" + "default_config" + "demo" + "denonavr" + "derivative" + "device_automation" + "device_sun_light_trigger" + "device_tracker" + "devolo_home_control" + "devolo_home_network" + "dexcom" + "dhcp" + "diagnostics" + "dialogflow" + "directv" + "discovery" + "dlna_dmr" + "dnsip" + "doorbird" + "dsmr" + "dte_energy_bridge" + "duckdns" + "dunehd" + "dynalite" + "eafm" + "ecobee" + "econet" + "efergy" + "elgato" + "elkm1" + "elmax" + "emonitor" + "emulated_hue" + "emulated_kasa" + "emulated_roku" + "energy" + "enocean" + "enphase_envoy" + "environment_canada" + "epson" + "esphome" + "everlights" + "evil_genius_labs" + "ezviz" + "faa_delays" + "facebook" + "facebox" + "fail2ban" + "fan" + "feedreader" + "ffmpeg" + "fido" + "file" + "filesize" + "filter" + "fireservicerota" + "firmata" + "fjaraskupan" + "flic" + "flick_electric" + "flipr" + "flo" + "flume" + "flunearyou" + "flux" + "flux_led" + "folder" + "folder_watcher" + "foobot" + "forecast_solar" + "foscam" + "freebox" + "freedns" + "freedompro" + "fritz" + "fritzbox" + "fritzbox_callmonitor" + "fronius" + "frontend" + "garages_amsterdam" + "gdacs" + "generic" + "generic_hygrostat" + "generic_thermostat" + "geo_json_events" + "geo_location" + "geo_rss_events" + "geofency" + "geonetnz_quakes" + "geonetnz_volcano" + "gios" + "github" + "glances" + "goalzero" + "gogogate2" + "goodwe" + "google" + "google_assistant" + "google_domains" + "google_pubsub" + "google_translate" + "google_travel_time" + "google_wifi" + "gpslogger" + "graphite" + "gree" + "group" + "growatt_server" + "guardian" + "habitica" + "hangouts" + "harmony" + "hassio" + "hddtemp" + "heos" + "here_travel_time" + "hisense_aehw4a1" + "history" + "history_stats" + "hive" + "hlk_sw16" + "home_connect" + "home_plus_control" + "homeassistant" + "homekit" + "homekit_controller" + "homematic" + "homematicip_cloud" + "homewizard" + "honeywell" + "html5" + "http" + "huawei_lte" + "hue" + "huisbaasje" + "humidifier" + "hunterdouglas_powerview" + "hvv_departures" + "hyperion" + "ialarm" + "iaqualink" + "icloud" + "ifttt" + "ign_sismologia" + "image" + "image_processing" + "imap_email_content" + "influxdb" + "input_boolean" + "input_button" + "input_datetime" + "input_number" + "input_select" + "input_text" + "insteon" + "integration" + "intellifire" + "intent" + "intent_script" + "ios" + "iotawatt" + "ipma" + "ipp" + "iqvia" + "islamic_prayer_times" + "isy994" + "izone" + "jellyfin" + "jewish_calendar" + "juicenet" + "keenetic_ndms2" + "kira" + "kmtronic" + "knx" + "kodi" + "konnected" + "kraken" + "kulersky" + "lastfm" + "launch_library" + "lcn" + "light" + "litterrobot" + "local_file" + "local_ip" + "locative" + "lock" + "logbook" + "logentries" + "logger" + "london_air" + "lookin" + "lovelace" + "luftdaten" + "lutron_caseta" + "lyric" + "mailbox" + "manual" + "manual_mqtt" + "maxcube" + "mazda" + "media_player" + "media_source" + "melcloud" + "meraki" + "met" + "met_eireann" + "meteoclimatic" + "mhz19" + "microsoft_face" + "microsoft_face_detect" + "microsoft_face_identify" + "mikrotik" + "mill" + "min_max" + "minecraft_server" + "minio" + "mobile_app" + "modbus" + "modem_callerid" + "modern_forms" + "mold_indicator" + "moon" + "motion_blinds" + "motioneye" + "mqtt" + "mqtt_eventstream" + "mqtt_json" + "mqtt_room" + "mqtt_statestream" + "mullvad" + "mutesync" + "my" + "myq" + "mysensors" + "mythicbeastsdns" + "nam" + "namecheapdns" + "nanoleaf" + "neato" + "ness_alarm" + "nest" + "netatmo" + "netgear" + "network" + "nexia" + "nightscout" + "nina" + "no_ip" + "notify" + "notion" + "nsw_rural_fire_service_feed" + "nuki" + "number" + "nut" + "nws" + "nx584" + "octoprint" + "omnilogic" + "onboarding" + "oncue" + "ondilo_ico" + "onewire" + "onvif" + "open_meteo" + "openalpr_cloud" + "openalpr_local" + "openerz" + "opengarage" + "openhardwaremonitor" + "opentherm_gw" + "openuv" + "openweathermap" + "opnsense" + "overkiz" + "ovo_energy" + "owntracks" + "ozw" + "p1_monitor" + "panel_custom" + "panel_iframe" + "persistent_notification" + "person" + "philips_js" + "pi_hole" + "picnic" + "ping" + "plaato" + "plant" + "plex" + "plugwise" + "point" + "poolsense" + "profiler" + "prometheus" + "prosegur" + "proximity" + "push" + "pushbullet" + "pvoutput" + "pvpc_hourly_pricing" + "python_script" + "qld_bushfire" + "rachio" + "radarr" + "rainforest_eagle" + "rainmachine" + "random" + "rdw" + "recollect_waste" + "recorder" + "reddit" + "remote" + "renault" + "rest" + "rest_command" + "rflink" + "rfxtrx" + "ridwell" + "ring" + "risco" + "rituals_perfume_genie" + "rmvtransport" + "roku" + "roomba" + "roon" + "rpi_power" + "rss_feed_template" + "rtsp_to_webrtc" + "ruckus_unleashed" + "safe_mode" + "samsungtv" + "scene" + "screenlogic" + "script" + "search" + "season" + "select" + "sense" + "senseme" + "sensor" + "sentry" + "seventeentrack" + "sharkiq" + "shell_command" + "shelly" + "shopping_list" + "sia" + "sigfox" + "sighthound" + "simplisafe" + "simulated" + "siren" + "slack" + "sleepiq" + "sma" + "smappee" + "smart_meter_texas" + "smarthab" + "smartthings" + "smarttub" + "smhi" + "smtp" + "snips" + "solaredge" + "solarlog" + "solax" + "soma" + "somfy" + "somfy_mylink" + "sonarr" + "songpal" + "sonos" + "soundtouch" + "spaceapi" + "spc" + "speedtestdotnet" + "spider" + "spotify" + "sql" + "squeezebox" + "srp_energy" + "ssdp" + "starline" + "startca" + "statistics" + "statsd" + "steamist" + "stream" + "stt" + "subaru" + "sun" + "surepetcare" + "switch" + "switchbot" + "switcher_kis" + "syncthing" + "syncthru" + "synology_dsm" + "system_bridge" + "system_health" + "system_log" + "tado" + "tag" + "tailscale" + "tasmota" + "tcp" + "telegram" + "tellduslive" + "template" + "tesla_wall_connector" + "threshold" + "tibber" + "tile" + "time_date" + "timer" + "tod" + "tolo" + "tomato" + "toon" + "totalconnect" + "tplink" + "traccar" + "trace" + "tractive" + "tradfri" + "trafikverket_weatherstation" + "transmission" + "transport_nsw" + "trend" + "tts" + "tuya" + "twentemilieu" + "twilio" + "twinkly" + "twitch" + "uk_transport" + "unifi" + "unifi_direct" + "universal" + "upb" + "upcloud" + "updater" + "upnp" + "uptime" + "uptimerobot" + "usb" + "usgs_earthquakes_feed" + "utility_meter" + "uvc" + "vacuum" + "velbus" + "venstar" + "vera" + "verisure" + "version" + "vesync" + "vicare" + "vilfo" + "vizio" + "vlc_telnet" + "voicerss" + "volumio" + "vultr" + "wake_on_lan" + "wallbox" + "water_heater" + "watttime" + "waze_travel_time" + "weather" + "webhook" + "webostv" + "websocket_api" + "wemo" + "whirlpool" + "whois" + "wiffi" + "wilight" + "wled" + "workday" + "worldclock" + "wsdot" + "xbox" + "xiaomi" + "xiaomi_aqara" + "xiaomi_miio" + "yale_smart_alarm" + "yamaha" + "yamaha_musiccast" + "yandex_transport" + "yandextts" + "yeelight" + "youless" + "zeroconf" + "zerproc" + "zha" + "zodiac" + "zone" + "zwave" + "zwave_js" + ]; } diff --git a/pkgs/servers/home-assistant/default.nix b/pkgs/servers/home-assistant/default.nix index b0d2063742391..920343de67b63 100644 --- a/pkgs/servers/home-assistant/default.nix +++ b/pkgs/servers/home-assistant/default.nix @@ -1,5 +1,6 @@ { stdenv , lib +, callPackage , fetchFromGitHub , fetchpatch , python3 @@ -14,6 +15,9 @@ # Additional packages to add to propagatedBuildInputs , extraPackages ? ps: [] +# Write out info about included extraComponents and extraPackages +, writeText + # Override Python packages using # self: super: { pkg = super.pkg.overridePythonAttrs (oldAttrs: { ... }); } # Applied after defaultOverrides @@ -24,104 +28,10 @@ let defaultOverrides = [ - # aiounify 29 breaks integration tests - (self: super: { - aiounifi = super.aiounifi.overridePythonAttrs (oldAttrs: rec { - version = "28"; - src = fetchFromGitHub { - owner = "Kane610"; - repo = "aiounifi"; - rev = "v${version}"; - sha256 = "1r86pk80sa1la2s7c6v9svh5cpkci6jcw1xziz0h09jdvv5j5iff"; - }; - }); - }) - # Override the version of some packages pinned in Home Assistant's setup.py and requirements_all.txt (mkOverride "python-slugify" "4.0.1" "69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270") (self: super: { - httpcore = super.httpcore.overridePythonAttrs (oldAttrs: rec { - version = "0.14.3"; - src = fetchFromGitHub { - owner = "encode"; - repo = "httpcore"; - rev = version; - sha256 = "sha256-jPsbMhY1lWKBXlh6hsX6DGKXi/g7VQSU00tF6H7qkOo="; - }; - propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [ python3.pkgs.certifi ]; - doCheck = false; - }); - }) - - (self: super: { - httpx = super.httpx.overridePythonAttrs (oldAttrs: rec { - version = "0.21.1"; - src = fetchFromGitHub { - owner = "encode"; - repo = "httpx"; - rev = version; - sha256 = "sha256-ayhLP+1hPWAx2ds227CKp5cebVkD5B2Z59L+3dzdINc="; - }; - doCheck = false; - }); - }) - - (self: super: { - pytest-httpx = super.pytest-httpx.overridePythonAttrs (oldAttrs: rec { - version = "0.15.0"; - src = fetchFromGitHub { - owner = "Colin-bin"; - repo = "pytest_httpx"; - rev = "v${version}"; - sha256 = "08dxvjkxlnam3r0yp17495d1vksyawzzkpykacjql1gi6hqlfrwg"; - }; - }); - }) - - (self: super: { - respx = super.respx.overridePythonAttrs (oldAttrs: rec { - version = "0.19.0"; - src = fetchFromGitHub { - owner = "lundberg"; - repo = "respx"; - rev = version; - sha256 = "sha256-xiAt42kc1+rro99KMwzYKi3XC+wxYVqOY11tM+M/uV8="; - }; - }); - }) - - (self: super: { - envoy-reader = super.envoy-reader.overridePythonAttrs (oldAttrs: rec { - patches = [ - # Support for later httpx, https://github.com/jesserizzo/envoy_reader/pull/82 - (fetchpatch { - name = "support-later-httpx.patch"; - url = "https://github.com/jesserizzo/envoy_reader/commit/6019a89419fe9c830ba839be7d39ec54725268b0.patch"; - sha256 = "17vsrx13rskvh8swvjisb2dk6x1jdbjcm8ikkpidia35pa24h272"; - }) - ]; - }); - }) - - (self: super: { - sanic = super.sanic.overridePythonAttrs (oldAttrs: rec { - version = "21.9.3"; - src = fetchFromGitHub { - owner = "sanic-org"; - repo = "sanic"; - rev = "v${version}"; - sha256 = "0m18jdw1mvf7jhpnrxhm96p24pxvv0h9m71a8c7sqqkwnnpa3p5i"; - }; - disabledTests = oldAttrs.disabledTests ++ [ - "test_redirect" - "test_chained_redirect" - "test_unix_connection" - ]; - }); - }) - - (self: super: { huawei-lte-api = super.huawei-lte-api.overridePythonAttrs (oldAttrs: rec { version = "1.4.18"; src = fetchFromGitHub { @@ -134,36 +44,6 @@ let }); }) - # Pinned due to API changes in iaqualink>=2.0, remove after - # https://github.com/home-assistant/core/pull/48137 was merged - (self: super: { - iaqualink = super.iaqualink.overridePythonAttrs (oldAttrs: rec { - version = "0.3.90"; - src = fetchFromGitHub { - owner = "flz"; - repo = "iaqualink-py"; - rev = "v${version}"; - sha256 = "0c8ckbbr1n8gx5k63ymgyfkbz3d0rbdvghg8fqdvbg4nrigrs5v0"; - }; - checkInputs = oldAttrs.checkInputs ++ [ python3.pkgs.asynctest ]; - }); - }) - - # Pinned due to API changes in influxdb-client>1.21.0 - (self: super: { - influxdb-client = super.influxdb-client.overridePythonAttrs (oldAttrs: rec { - version = "1.21.0"; - src = fetchFromGitHub { - owner = "influxdata"; - repo = "influxdb-client-python"; - rev = "v${version}"; - sha256 = "081pwd3aa7kbgxqcl1hfi2ny4iapnxkcp9ypsfslr69d0khvfc4s"; - }; - }); - }) - - (mkOverride "jinja2" "3.0.3" "1mvwr02s86zck5wsmd9wjxxb9iaqr17hdi5xza9vkwv8rmrv46v1") - # Pinned due to API changes in pyruckus>0.12 (self: super: { pyruckus = super.pyruckus.overridePythonAttrs (oldAttrs: rec { @@ -177,22 +57,22 @@ let }); }) - # Pinned due to API changes in eebrightbox>=0.0.5 + # Pinned due to API changes in 0.1.0 + (mkOverride "poolsense" "0.0.8" "09y4fq0gdvgkfsykpxnvmfv92dpbknnq5v82spz43ak6hjnhgcyp") + + # Pinned due to API changes >0.3.5.3 (self: super: { - eebrightbox = super.eebrightbox.overridePythonAttrs (oldAttrs: rec { - version = "0.0.4"; + pyatag = super.pyatag.overridePythonAttrs (oldAttrs: rec { + version = "0.3.5.3"; src = fetchFromGitHub { - owner = "krygal"; - repo = "eebrightbox"; + owner = "MatsNl"; + repo = "pyatag"; rev = version; - sha256 = "0d8mmpwgrd7gymw5263r1v2wjv6dx6w6pq13d62fkfm4h2hya4a4"; + sha256 = "00ly4injmgrj34p0lyx7cz2crgnfcijmzc0540gf7hpwha0marf6"; }; }); }) - # Pinned due to API changes in 0.1.0 - (mkOverride "poolsense" "0.0.8" "09y4fq0gdvgkfsykpxnvmfv92dpbknnq5v82spz43ak6hjnhgcyp") - # Pinned due to API changes in 0.4.0 (self: super: { vilfo-api-client = super.vilfo-api-client.overridePythonAttrs (oldAttrs: rec { @@ -219,28 +99,15 @@ let }); }) - # Remove with 2021.12.6 as the requirement will be 1.1.16 (at least) - (self: super: { - yalexs = super.yalexs.overridePythonAttrs (oldAttrs: rec { - version = "1.1.13"; - src = fetchFromGitHub { - owner = "bdraco"; - repo = "yalexs"; - rev = "v${version}"; - sha256 = "sha256-lnx8+VyDyO7Wg+QW+CC0FUg77Ndfjar6PLsDYwEpaCQ="; - }; - }); - }) - # home-assistant-frontend does not exist in python3.pkgs (self: super: { home-assistant-frontend = self.callPackage ./frontend.nix { }; }) ]; - mkOverride = attrname: version: sha256: + mkOverride = attrName: version: sha256: self: super: { - ${attrname} = super.${attrname}.overridePythonAttrs (oldAttrs: { + ${attrName} = super.${attrName}.overridePythonAttrs (oldAttrs: { inherit version; src = oldAttrs.src.override { inherit version sha256; @@ -248,7 +115,7 @@ let }); }; - py = python3.override { + python = python3.override { # Put packageOverrides at the start so they are applied after defaultOverrides packageOverrides = lib.foldr lib.composeExtensions (self: super: { }) ([ packageOverrides ] ++ defaultOverrides); }; @@ -257,22 +124,29 @@ let availableComponents = builtins.attrNames componentPackages.components; - getPackages = component: builtins.getAttr component componentPackages.components; + inherit (componentPackages) supportedComponentsWithTests; - componentBuildInputs = lib.concatMap (component: getPackages component py.pkgs) extraComponents; + getPackages = component: componentPackages.components.${component}; + + componentBuildInputs = lib.concatMap (component: getPackages component python.pkgs) extraComponents; # Ensure that we are using a consistent package set - extraBuildInputs = extraPackages py.pkgs; + extraBuildInputs = extraPackages python.pkgs; + + # Create info about included packages and components + extraComponentsFile = writeText "home-assistant-components" (lib.concatStringsSep "\n" extraComponents); + extraPackagesFile = writeText "home-assistant-packages" (lib.concatMapStringsSep "\n" (pkg: pkg.pname) extraBuildInputs); # Don't forget to run parse-requirements.py after updating - hassVersion = "2021.12.7"; + hassVersion = "2022.2.9"; -in with py.pkgs; buildPythonApplication rec { +in python.pkgs.buildPythonApplication rec { pname = "homeassistant"; version = assert (componentPackages.version == hassVersion); hassVersion; + format = "pyproject"; # check REQUIRED_PYTHON_VER in homeassistant/const.py - disabled = pythonOlder "3.8"; + disabled = python.pythonOlder "3.9"; # don't try and fail to strip 6600+ python files, it takes minutes! dontStrip = true; @@ -282,7 +156,7 @@ in with py.pkgs; buildPythonApplication rec { owner = "home-assistant"; repo = "core"; rev = version; - hash = "sha256:0jcnk43wm3xwvsfyvbswq681v2c3xmki1bakn0l12j6paida784y"; + hash = "sha256-So/MAKyFVa1TchrVE4ego1fRbgOXCoXR3w/rJLFSBqI="; }; # leave this in, so users don't have to constantly update their downstream patch handling @@ -291,23 +165,32 @@ in with py.pkgs; buildPythonApplication rec { src = ./patches/ffmpeg-path.patch; ffmpeg = "${lib.getBin ffmpeg}/bin/ffmpeg"; }) - ./patches/tests-ignore-OSErrors-in-hass-fixture.patch ]; - postPatch = '' - substituteInPlace setup.py \ - --replace "aiohttp==3.8.1" "aiohttp" \ - --replace "async_timeout==4.0.0" "async_timeout" \ - --replace "bcrypt==3.1.7" "bcrypt" \ - --replace "cryptography==35.0.0" "cryptography" \ - --replace "httpx==0.21.0" "httpx" \ - --replace "pip>=8.0.3,<20.3" "pip" \ - --replace "pyyaml==6.0" "pyyaml" \ - --replace "yarl==1.6.3" "yarl" + postPatch = let + relaxedConstraints = [ + "aiohttp" + "async_timeout" + "attrs" + "awesomeversion" + "bcrypt" + "cryptography" + "httpx" + "pip" + "PyJWT" + "requests" + "yarl" + ]; + in '' + sed -r -i \ + ${lib.concatStringsSep "\n" (map (package: + ''-e 's@${package}[<>=]+.*@${package}@g' \'' + ) relaxedConstraints)} + setup.cfg substituteInPlace tests/test_config.py --replace '"/usr"' '"/build/media"' ''; - propagatedBuildInputs = [ + propagatedBuildInputs = with python.pkgs; [ # Only packages required in setup.py aiohttp astral @@ -334,8 +217,6 @@ in with py.pkgs; buildPythonApplication rec { yarl # Not in setup.py, but used in homeassistant/util/package.py setuptools - ] ++ lib.optionals (pythonOlder "3.9") [ - backports-zoneinfo ] ++ componentBuildInputs ++ extraBuildInputs; makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip"; @@ -343,9 +224,10 @@ in with py.pkgs; buildPythonApplication rec { # upstream only tests on Linux, so do we. doCheck = stdenv.isLinux; - checkInputs = [ + checkInputs = with python.pkgs; [ # test infrastructure (selectively from requirement_test.txt) freezegun + jsonpickle pytest-aiohttp pytest-freezegun pytest-mock @@ -354,541 +236,18 @@ in with py.pkgs; buildPythonApplication rec { pytest-xdist pytestCheckHook requests-mock - stdlib-list - jsonpickle respx + stdlib-list + tqdm + # required by tests/pylint + astroid + pylint # required by tests/auth/mfa_modules pyotp - ] ++ lib.concatMap (component: getPackages component py.pkgs) componentTests; - - # We can reasonably test components that don't communicate with any network - # services. Before adding new components to this list make sure we have all - # its dependencies packaged and listed in ./component-packages.nix. - componentTests = [ - "abode" - "accuweather" - "acmeda" - "adguard" - "advantage_air" - "aemet" - "agent_dvr" - "air_quality" - "airly" - "airnow" - "airthings" - "airvisual" - "alarm_control_panel" - "alarmdecoder" - "alert" - "alexa" - "almond" - "ambiclimate" - "ambient_station" - "analytics" - "androidtv" - "apache_kafka" - "api" - "apple_tv" - "apprise" - "aprs" - "arcam_fmj" - "arlo" - "asuswrt" - "atag" - "august" - "aurora" - "auth" - "automation" - "awair" - "aws" - "axis" - "azure_devops" - "azure_event_hub" - "bayesian" - "binary_sensor" - "blackbird" - "blebox" - "blink" - "blueprint" - "bluetooth_le_tracker" - "bmw_connected_drive" - "bond" - "bosch_shc" - "braviatv" - "broadlink" - "brother" - "bsblan" - "buienradar" - "caldav" - "calendar" - "camera" - "canary" - "cast" - "cert_expiry" - "climacell" - "climate" - "cloud" - "cloudflare" - "color_extractor" - "comfoconnect" - "command_line" - "compensation" - "config" - "configurator" - "control4" - "conversation" - "coolmaster" - "coronavirus" - "counter" - "cover" - "daikin" - "darksky" - "datadog" - "deconz" + ] ++ lib.concatMap (component: getPackages component python.pkgs) [ + # some components are needed even if tests in tests/components are disabled "default_config" - "demo" - "denonavr" - "derivative" - "device_automation" - "device_sun_light_trigger" - "device_tracker" - "devolo_home_control" - "dexcom" - "dhcp" - "dialogflow" - "directv" - "discovery" - "doorbird" - "dsmr" - "dte_energy_bridge" - "duckdns" - "dunehd" - "eafm" - "ecobee" - "econet" - "ee_brightbox" - "efergy" - "elgato" - "elkm1" - "emonitor" - "emulated_hue" - "emulated_kasa" - "emulated_roku" - "enocean" - "enphase_envoy" - "epson" - "esphome" - "everlights" - "ezviz" - "faa_delays" - "facebook" - "facebox" - "fail2ban" - "fan" - "feedreader" - "ffmpeg" - "fido" - "file" - "filesize" - "filter" - "fireservicerota" - "firmata" - "fjaraskupan" - "flick_electric" - "flipr" - "flo" - "flume" - "flunearyou" - "flux" - "folder" - "folder_watcher" - "foobot" - "foscam" - "freebox" - "freedns" - "fritz" - "fritzbox" - "fritzbox_callmonitor" - "frontend" - "garages_amsterdam" - "gdacs" - "generic" - "generic_thermostat" - "geo_json_events" - "geo_location" - "geo_rss_events" - "geofency" - "geonetnz_quakes" - "geonetnz_volcano" - "gios" - # updated to incompatible version and overriding is annoying because of async_timeout<4 pin - # "glances" - "goalzero" - "gogogate2" - "google" - "google_assistant" - "google_domains" - "google_pubsub" - "google_translate" - "google_travel_time" - "google_wifi" - "gpslogger" - "graphite" - "gree" - "group" - "growatt_server" - "guardian" - "habitica" - "hangouts" - "harmony" - "hassio" - "hddtemp" - "heos" - "here_travel_time" - "hisense_aehw4a1" - "history" - "history_stats" - "hive" - "hlk_sw16" - "home_connect" - "home_plus_control" - "homeassistant" - # disable homekit tests because they fail in the network component - #"homekit" - "homekit_controller" - "homematic" - "homematicip_cloud" - "honeywell" - "html5" - "http" - "huawei_lte" "hue" - "huisbaasje" - "humidifier" - "hunterdouglas_powerview" - "hvv_departures" - "hyperion" - "ialarm" - "iaqualink" - "icloud" - "ifttt" - "ign_sismologia" - "image" - "image_processing" - "imap_email_content" - "influxdb" - "input_boolean" - "input_datetime" - "input_number" - "input_select" - "input_text" - "insteon" - "integration" - "intent" - "intent_script" - "ios" - "ipma" - "ipp" - "iqvia" - "islamic_prayer_times" - "isy994" - "izone" - "jewish_calendar" - "juicenet" - "keenetic_ndms2" - "kira" - "kmtronic" - "knx" - "kodi" - "konnected" - "kraken" - "kulersky" - "lastfm" - "lcn" - "light" - "litterrobot" - "local_file" - "local_ip" - "locative" - "lock" - "logbook" - "logentries" - "logger" - "london_air" - "lovelace" - "luftdaten" - "lutron_caseta" - "lyric" - "mailbox" - "manual" - "manual_mqtt" - "maxcube" - "mazda" - "media_player" - "media_source" - "meraki" - "met" - "met_eireann" - "meteoclimatic" - "mhz19" - "microsoft_face" - "microsoft_face_detect" - "microsoft_face_identify" - "mikrotik" - "mill" - "min_max" - "minecraft_server" - "minio" - "mobile_app" - "modbus" - "mold_indicator" - "moon" - "motion_blinds" - "motioneye" - "mqtt" - "mqtt_eventstream" - "mqtt_json" - "mqtt_room" - "mqtt_statestream" - "mullvad" - "mutesync" - "my" - "myq" - "mysensors" - "mythicbeastsdns" - "nam" - "namecheapdns" - "neato" - "ness_alarm" - # python-nest has an unfree license, this prevents builds through ofborg - # "nest" - "netatmo" - "nexia" - "nightscout" - "no_ip" - "notify" - "notion" - "nsw_rural_fire_service_feed" - "nuki" - "number" - "nws" - "nx584" - "octoprint" - "omnilogic" - "onboarding" - "ondilo_ico" - "openalpr_cloud" - "openalpr_local" - "openerz" - "openhardwaremonitor" - "opentherm_gw" - "openuv" - "openweathermap" - "opnsense" - "ovo_energy" - "owntracks" - "ozw" - "p1_monitor" - "panel_custom" - "panel_iframe" - "persistent_notification" - "person" - "philips_js" - "pi_hole" - "picnic" - "ping" - "plaato" - "plant" - "plex" - "plugwise" - "point" - "poolsense" - "profiler" - "prometheus" - "proximity" - "push" - "pushbullet" - "pvpc_hourly_pricing" - "python_script" - "qld_bushfire" - "rachio" - "radarr" - "rainmachine" - "random" - "recollect_waste" - "recorder" - "reddit" - "remote" - "renault" - "rest" - "rest_command" - "rflink" - "rfxtrx" - "ring" - "risco" - "rituals_perfume_genie" - "rmvtransport" - "roku" - "roomba" - "roon" - "rss_feed_template" - "ruckus_unleashed" - "safe_mode" - "samsungtv" - "scene" - "screenlogic" - "script" - "search" - "season" - "sense" - "sensor" - "sentry" - "sharkiq" - "shell_command" - "shelly" - "shopping_list" - "sia" - "sigfox" - "sighthound" - "simplisafe" - "simulated" - "slack" - "sleepiq" - "sma" - "smappee" - "smart_meter_texas" - "smarthab" - "smartthings" - "smarttub" - "smhi" - "smtp" - "snips" - "solaredge" - "soma" - "somfy" - "somfy_mylink" - "sonarr" - "songpal" - # disable sonos components test because they rely on ssdp, which doesn't work in our sandbox - # "sonos" - "soundtouch" - "spaceapi" - "spc" - "speedtestdotnet" - "spider" - "spotify" - "sql" - "squeezebox" - "srp_energy" - "ssdp" - "starline" - "startca" - "statistics" - "statsd" - "stream" - "stt" - "subaru" - "sun" - "surepetcare" - "switch" - "switcher_kis" - "syncthing" - "syncthru" - "synology_dsm" - "system_health" - "system_log" - "tado" - "tag" - "tasmota" - "tcp" - "telegram" - "tellduslive" - "template" - "threshold" - "tibber" - "tile" - "time_date" - "timer" - "tod" - "tomato" - "toon" - "totalconnect" - "tplink" - "traccar" - "trace" - "tradfri" - "transmission" - "transport_nsw" - "trend" - "tts" - "tuya" - "twentemilieu" - "twilio" - "twinkly" - "twitch" - "uk_transport" - "unifi" - "unifi_direct" - "universal" - "upb" - "upcloud" - "updater" - # disabled, because it tries to join a multicast group and fails to find a usable network interface - # "upnp" - "uptime" - "uptimerobot" - "usgs_earthquakes_feed" - "utility_meter" - "uvc" - "vacuum" - "velbus" - # disabled, because it includes onewire component tests, for which we lack p1wire dependency - # "venstar" - "vera" - "verisure" - "version" - "vesync" - "vilfo" - "vizio" - "vlc_telnet" - "voicerss" - "volumio" - "vultr" - "wake_on_lan" - "wallbox" - "water_heater" - "waze_travel_time" - "weather" - "webhook" - "webostv" - "websocket_api" - "wemo" - "wiffi" - "wilight" - "wled" - "workday" - "worldclock" - "wsdot" - "xbox" - "xiaomi" - "xiaomi_aqara" - # disabled, because we require cryptography>=35.0 for the miio package - # "xiaomi_miio" - "yamaha" - "yandex_transport" - "yandextts" - "yeelight" - "youless" - # disabled, because it tries to join a multicast group and fails to find a usable network interface - # "zeroconf" - "zerproc" - "zha" - "zodiac" - "zone" - "zwave" - "zwave_js" - ] ++ lib.optionals (builtins.any (s: s == stdenv.hostPlatform.system) debugpy.meta.platforms) [ - "debugpy" ]; pytestFlagsArray = [ @@ -901,117 +260,51 @@ in with py.pkgs; buildPythonApplication rec { "--only-rerun RuntimeError" # enable full variable printing on error "--showlocals" - # here_travel_time/test_sensor.py: Tries to access HERE API: herepy.error.HEREError: Error occured on __get - "--deselect tests/components/here_travel_time/test_sensor.py::test_invalid_credentials" - # screenlogic/test_config_flow.py: Tries to send out UDP broadcasts - "--deselect tests/components/screenlogic/test_config_flow.py::test_form_cannot_connect" - # abode/test_camera.py: Race condition in pickle file creationg - "--deselect tests/components/abode/test_camera.py::test_camera_off" - # asuswrt/test_config_flow.py: Sandbox network limitations, fails with unexpected error - "--deselect tests/components/asuswrt/test_config_flow.py::test_on_connect_failed" - # shelly/test_config_flow.py: Tries to join multicast group - "--deselect tests/components/shelly/test_config_flow.py::test_form" - "--deselect tests/components/shelly/test_config_flow.py::test_title_without_name" - "--deselect tests/components/shelly/test_config_flow.py::test_form_auth" - "--deselect tests/components/shelly/test_config_flow.py::test_form_errors_test_connection" - "--deselect tests/components/shelly/test_config_flow.py::test_user_setup_ignored_device" - "--deselect tests/components/shelly/test_config_flow.py::test_form_auth_errors_test_connection" - "--deselect tests/components/shelly/test_config_flow.py::test_form_auth_errors_test_connection" - "--deselect tests/components/shelly/test_config_flow.py::test_form_auth_errors_test_connection" - "--deselect tests/components/shelly/test_config_flow.py::test_zeroconf" - "--deselect tests/components/shelly/test_config_flow.py::test_zeroconf_sleeping_device" - "--deselect tests/components/shelly/test_config_flow.py::test_zeroconf_sleeping_device_error" - "--deselect tests/components/shelly/test_config_flow.py::test_zeroconf_sleeping_device_error" - "--deselect tests/components/shelly/test_config_flow.py::test_zeroconf_require_auth" - # prometheus/test_init.py: Spurious AssertionError regarding humidifier_target_humidity_percent metric - "--deselect tests/components/prometheus/test_init.py::test_view" - # smhi/test_init.py: Tries to fetch data from the network: socket.gaierror: [Errno -2] Name or service not known - "--deselect tests/components/smhi/test_init.py::test_remove_entry" - # wallbox/test_config_flow.py: Tries to connect to api.wall-box.cim: Failed to establish a new connection: [Errno -2] Name or service not known - "--deselect tests/components/wallbox/test_config_flow.py::test_form_invalid_auth" - "--deselect tests/components/wallbox/test_config_flow.py::test_form_cannot_connect" - # default_config/test_init.py: Tries to check for updates and fails ungracefully without network access - "--deselect tests/components/default_config/test_init.py::test_setup" - # local_ip/test_{init,config_flow}.py: tries to lookup a route towards a multicast address and fails - "--deselect tests/components/local_ip/test_init.py::test_basic_setup" - "--deselect tests/components/local_ip/test_config_flow.py::test_config_flow" - # netatmo/test_select.py: NoneType object has no attribute state - "--deselect tests/components/netatmo/test_select.py::test_select_schedule_thermostats" - # wemo/test_sensor.py: KeyError for various power attributes - "--deselect tests/components/wemo/test_sensor.py::TestInsightTodayEnergy::test_state_unavailable" - "--deselect tests/components/wemo/test_sensor.py::TestInsightCurrentPower::test_state_unavailable" # helpers/test_system_info.py: AssertionError: assert 'Unknown' == 'Home Assistant Container' "--deselect tests/helpers/test_system_info.py::test_container_installationtype" # tests are located in tests/ "tests" - # dynamically add packages required for component tests - ] ++ map (component: "tests/components/" + component) componentTests; + ]; disabledTestPaths = [ # don't bulk test all components "tests/components" # pyotp since v2.4.0 complains about the short mock keys, hass pins v2.3.0 "tests/auth/mfa_modules/test_notify.py" - # emulated_hue/test_upnp.py: Tries to establish the public ipv4 address - "tests/components/emulated_hue/test_upnp.py" - # tado/test_{climate,water_heater}.py: Tries to connect to my.tado.com - "tests/components/tado/test_climate.py" - "tests/components/tado/test_water_heater.py" ]; disabledTests = [ # AssertionError: assert 1 == 0 - "test_error_posted_as_event" "test_merge" - # ModuleNotFoundError: No module named 'pyqwikswitch' - "test_merge_id_schema" - # keyring.errors.NoKeyringError: No recommended backend was available. - "test_secrets_from_unrelated_fails" - "test_secrets_credstash" - # generic/test_camera.py: AssertionError: 500 == 200 - "test_fetching_without_verify_ssl" - "test_fetching_url_with_verify_ssl" - # util/test_package.py: AssertionError on package.is_installed('homeassistant>=999.999.999') - "test_check_package_version_does_not_match" - # homeassistant/util/thread.py:51: SystemError - "test_executor_shutdown_can_interrupt_threads" - # {'theme_color': '#03A9F4'} != {'theme_color': 'blue'} - "test_webhook_handle_get_config" - # onboarding tests rpi_power component, for which we are lacking rpi_bad_power library - "test_onboarding_core_sets_up_rpi_power" - "test_onboarding_core_no_rpi_power" - # hue/test_sensor_base.py: Race condition when counting events - "test_hue_events" - # august/test_lock.py: AssertionError: assert 'unlocked' == 'locked' / assert 'off' == 'on' - "test_lock_update_via_pubnub" - "test_door_sense_update_via_pubnub" + # Tests are flaky + "test_config_platform_valid" ]; preCheck = '' export HOME="$TEMPDIR" - patch -p1 < ${./patches/tests-mock-source-ip.patch} - # the tests require the existance of a media dir mkdir /build/media # put ping binary into PATH, e.g. for wake_on_lan tests export PATH=${inetutils}/bin:$PATH + ''; - # error out when component test directory is missing, otherwise hidden by xdist execution :( - for component in ${lib.concatStringsSep " " (map lib.escapeShellArg componentTests)}; do - test -d "tests/components/$component" || { - >2& echo "ERROR: Tests for component '$component' were enabled, but they do not exist!" - exit 1 - } - done + postInstall = '' + cp -v ${extraComponentsFile} $out/extra_components + cp -v ${extraPackagesFile} $out/extra_packages ''; passthru = { - inherit availableComponents extraComponents; - python = py; + inherit + availableComponents + extraComponents + getPackages + python + supportedComponentsWithTests; tests = { - inherit (nixosTests) home-assistant; + nixos = nixosTests.home-assistant; + components = callPackage ./tests.nix { }; }; }; diff --git a/pkgs/servers/home-assistant/frontend.nix b/pkgs/servers/home-assistant/frontend.nix index a3ca2c07cdcf4..2aabb0d9312cd 100644 --- a/pkgs/servers/home-assistant/frontend.nix +++ b/pkgs/servers/home-assistant/frontend.nix @@ -4,11 +4,15 @@ 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 = "20211229.0"; + version = "20220203.1"; + format = "wheel"; src = fetchPypi { - inherit pname version; - sha256 = "sha256-2hACC2542jz1DID7nV28keVVDDBOLW1QDYTLM4S1ZJ0="; + inherit version format; + pname = "home_assistant_frontend"; + dist = "py3"; + python = "py3"; + sha256 = "sha256-6+TzBhHo9+eo6Hlk8RF+BAt4O0i759iAN+dKAPDmTNY="; }; # there is nothing to strip in this package diff --git a/pkgs/servers/home-assistant/parse-requirements.py b/pkgs/servers/home-assistant/parse-requirements.py index 2cdc44caaae9b..fbe46b2377876 100755 --- a/pkgs/servers/home-assistant/parse-requirements.py +++ b/pkgs/servers/home-assistant/parse-requirements.py @@ -62,6 +62,7 @@ def get_version(): def parse_components(version: str = "master"): components = {} + components_with_tests = [] with tempfile.TemporaryDirectory() as tmp: with urlopen( f"https://github.com/home-assistant/home-assistant/archive/{version}.tar.gz" @@ -69,9 +70,13 @@ def parse_components(version: str = "master"): tarfile.open(fileobj=BytesIO(response.read())).extractall(tmp) # Use part of a script from the Home Assistant codebase core_path = os.path.join(tmp, f"core-{version}") + + for entry in os.scandir(os.path.join(core_path, "tests/components")): + if entry.is_dir(): + components_with_tests.append(entry.name) + sys.path.append(core_path) from script.hassfest.model import Integration - integrations = Integration.load_dir( pathlib.Path( os.path.join(core_path, "homeassistant/components") @@ -79,8 +84,10 @@ def parse_components(version: str = "master"): ) for domain in sorted(integrations): integration = integrations[domain] - components[domain] = integration.manifest - return components + if not integration.disabled: + components[domain] = integration.manifest + + return components, components_with_tests # Recursively get the requirements of a component and its dependencies @@ -161,7 +168,7 @@ def main() -> None: packages = dump_packages() version = get_version() print("Generating component-packages.nix for version {}".format(version)) - components = parse_components(version=version) + components, components_with_tests = parse_components(version=version) build_inputs = {} outdated = {} for component in sorted(components.keys()): @@ -204,6 +211,13 @@ def main() -> None: f.write(f" # missing inputs: {' '.join(missing)}") f.write("\n") f.write(" };\n") + f.write(" # components listed in tests/components for which all dependencies are packaged\n") + f.write(" supportedComponentsWithTests = [\n") + for component, deps in build_inputs.items(): + available, missing = deps + if len(missing) == 0 and component in components_with_tests: + f.write(f' "{component}"' + "\n") + f.write(" ];\n") f.write("}\n") supported_components = reduce(lambda n, c: n + (build_inputs[c][1] == []), diff --git a/pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch b/pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch deleted file mode 100644 index add0ea1d5521f..0000000000000 --- a/pkgs/servers/home-assistant/patches/tests-ignore-OSErrors-in-hass-fixture.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 3e3f5c37252a33ea1e71c39f2ca0f13940c261ad Mon Sep 17 00:00:00 2001 -From: Martin Weinelt <hexa@darmstadt.ccc.de> -Date: Sat, 17 Jul 2021 16:11:23 +0200 -Subject: [PATCH] tests: ignore OSErrors in hass fixture - -The nix sandbox will cause OSErrors due to limitations imposed on -network interaction. This change makes it so we forgive these cases. ---- - tests/conftest.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/tests/conftest.py b/tests/conftest.py -index 1f5ffc80d0..b284727a0f 100644 ---- a/tests/conftest.py -+++ b/tests/conftest.py -@@ -168,6 +168,8 @@ def hass(loop, load_registries, hass_storage, request): - continue - if isinstance(ex, ServiceNotFound): - continue -+ if isinstance(ex, OSError): -+ continue - raise ex - - --- -2.32.0 - diff --git a/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch b/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch index 4094d08ee7ff8..6812ee1915bb0 100644 --- a/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch +++ b/pkgs/servers/home-assistant/patches/tests-mock-source-ip.patch @@ -1,8 +1,8 @@ diff --git a/homeassistant/components/network/__init__.py b/homeassistant/components/network/__init__.py -index 7cc864727d..69333a5454 100644 +index b3ef88e7ab..b7a8471e1a 100644 --- a/homeassistant/components/network/__init__.py +++ b/homeassistant/components/network/__init__.py -@@ -26,7 +26,7 @@ async def async_get_source_ip( +@@ -30,7 +30,7 @@ async def async_get_source_ip( ) -> str: """Get the source ip for a target ip.""" adapters = await async_get_adapters(hass) diff --git a/pkgs/servers/home-assistant/tests.nix b/pkgs/servers/home-assistant/tests.nix new file mode 100644 index 0000000000000..31dbe64725cec --- /dev/null +++ b/pkgs/servers/home-assistant/tests.nix @@ -0,0 +1,67 @@ +{ lib +, home-assistant +}: + +let + # some components' tests have additional dependencies + extraCheckInputs = with home-assistant.python.pkgs; { + alexa = [ ha-av ]; + camera = [ ha-av ]; + cloud = [ mutagen ]; + config = [ pydispatcher ]; + generic = [ ha-av ]; + google_translate = [ mutagen ]; + nest = [ ha-av ]; + onboarding = [ pymetno rpi-bad-power ]; + version = [ aioaseko ]; + voicerss = [ mutagen ]; + yandextts = [ mutagen ]; + zha = [ pydeconz ]; + zwave_js = [ homeassistant-pyozw ]; + }; + + extraDisabledTestPaths = { + tado = [ + # tado/test_{climate,water_heater}.py: Tries to connect to my.tado.com + "tests/components/tado/test_climate.py" + "tests/components/tado/test_water_heater.py" + ]; + }; + + extraPytestFlagsArray = { + asuswrt = [ + # asuswrt/test_config_flow.py: Sandbox network limitations, fails with unexpected error + "--deselect tests/components/asuswrt/test_config_flow.py::test_on_connect_failed" + ]; + }; +in lib.listToAttrs (map (component: lib.nameValuePair component ( + home-assistant.overridePythonAttrs (old: { + pname = "homeassistant-test-${component}"; + + dontBuild = true; + dontInstall = true; + + checkInputs = old.checkInputs + ++ home-assistant.getPackages component home-assistant.python.pkgs + ++ extraCheckInputs.${component} or [ ]; + + disabledTestPaths = old.disabledTestPaths ++ extraDisabledTestPaths.${component} or [ ]; + + pytestFlagsArray = lib.remove "tests" old.pytestFlagsArray + ++ extraPytestFlagsArray.${component} or [ ] + ++ [ "tests/components/${component}" ]; + + preCheck = old.preCheck + lib.optionalString (builtins.elem component [ "emulated_hue" "songpal" "system_log" ]) '' + patch -p1 < ${./patches/tests-mock-source-ip.patch} + ''; + + meta = old.meta // { + broken = lib.elem component [ + "airtouch4" + "dnsip" + ]; + # upstream only tests on Linux, so do we. + platforms = lib.platforms.linux; + }; + }) +)) home-assistant.supportedComponentsWithTests) |