Merge pull request #34494 from dotlambda/home-assistant

home-assistant: compute extraComponents from config

authored by

Frederik Rietdijk and committed by
GitHub
db58049f c2b84b27

+581 -10
+31 -5
nixos/modules/services/misc/home-assistant.nix
··· 6 6 cfg = config.services.home-assistant; 7 7 8 8 configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config); 9 + 10 + availableComponents = pkgs.home-assistant.availableComponents; 11 + 12 + # Returns whether component is used in config 13 + useComponent = component: hasAttrByPath (splitString "." component) cfg.config; 14 + 15 + # List of components used in config 16 + extraComponents = filter useComponent availableComponents; 17 + 18 + package = if cfg.autoExtraComponents 19 + then (cfg.package.override { inherit extraComponents; }) 20 + else cfg.package; 21 + 9 22 in { 10 23 meta.maintainers = with maintainers; [ dotlambda ]; 11 24 ··· 29 42 }; 30 43 frontend = { }; 31 44 http = { }; 45 + feedreader.urls = [ "https://nixos.org/blogs.xml" ]; 32 46 } 33 47 ''; 34 48 description = '' ··· 48 62 ''; 49 63 description = '' 50 64 Home Assistant package to use. 51 - Most Home Assistant components require additional dependencies, 52 - which are best specified by overriding <literal>pkgs.home-assistant</literal>. 53 - You can find the dependencies by searching for failed imports in your log or by looking at this list: 54 - <link xlink:href="https://github.com/home-assistant/home-assistant/blob/master/requirements_all.txt"/> 65 + Override <literal>extraPackages</literal> in order to add additional dependencies. 66 + ''; 67 + }; 68 + 69 + autoExtraComponents = mkOption { 70 + default = true; 71 + type = types.bool; 72 + description = '' 73 + If set to <literal>true</literal>, the components used in <literal>config</config> 74 + are set as the specified package's <literal>extraComponents</literal>. 75 + This in turn adds all packaged dependencies to the derivation. 76 + You might still see import errors in your log. 77 + In this case, you will need to package the necessary dependencies yourself 78 + or ask for someone else to package them. 79 + If a dependency is packaged but not automatically added to this list, 80 + you might need to specify it in <literal>extraPackages</literal>. 55 81 ''; 56 82 }; 57 83 }; ··· 67 93 ''; 68 94 serviceConfig = { 69 95 ExecStart = '' 70 - ${cfg.package}/bin/hass --config "${cfg.configDir}" 96 + ${package}/bin/hass --config "${cfg.configDir}" 71 97 ''; 72 98 User = "hass"; 73 99 Group = "hass";
+6 -1
nixos/tests/home-assistant.nix
··· 17 17 homeassistant = { 18 18 name = "Home"; 19 19 time_zone = "UTC"; 20 + latitude = "0.0"; 21 + longitude = "0.0"; 22 + elevation = 0; 20 23 }; 21 24 frontend = { }; 22 25 http = { }; 23 26 }; 24 27 }; 25 28 }; 26 - }; 29 + }; 27 30 28 31 testScript = '' 29 32 startAll; ··· 37 40 $hass->waitForOpenPort(8123); 38 41 $hass->succeed("curl --fail http://localhost:8123/states"); 39 42 $hass->succeed("curl --fail http://localhost:8123/api/ | grep 'API running'"); 43 + 44 + $hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR"); 40 45 ''; 41 46 })
+431
pkgs/servers/home-assistant/component-packages.nix
··· 1 + # Generated from parse-requirements.py 2 + # Do not edit! 3 + 4 + { 5 + version = "0.62.1"; 6 + components = { 7 + "nuimo_controller" = ps: with ps; [ ]; 8 + "bbb_gpio" = ps: with ps; [ ]; 9 + "doorbird" = ps: with ps; [ ]; 10 + "isy994" = ps: with ps; [ ]; 11 + "notify.html5" = ps: with ps; [ pyjwt ]; 12 + "sensor.mvglive" = ps: with ps; [ ]; 13 + "arduino" = ps: with ps; [ ]; 14 + "xiaomi_aqara" = ps: with ps; [ ]; 15 + "rpi_gpio" = ps: with ps; [ ]; 16 + "remember_the_milk" = ps: with ps; [ httplib2 ]; 17 + "media_player.sonos" = ps: with ps; [ ]; 18 + "sensor.travisci" = ps: with ps; [ ]; 19 + "notify.twitter" = ps: with ps; [ ]; 20 + "notify.yessssms" = ps: with ps; [ ]; 21 + "abode" = ps: with ps; [ ]; 22 + "device_tracker.automatic" = ps: with ps; [ ]; 23 + "sensor.dnsip" = ps: with ps; [ aiodns ]; 24 + "emulated_hue" = ps: with ps; [ aiohttp-cors ]; 25 + "http" = ps: with ps; [ aiohttp-cors ]; 26 + "sensor.imap" = ps: with ps; [ ]; 27 + "light.lifx" = ps: with ps; [ ]; 28 + "scene.hunterdouglas_powerview" = ps: with ps; [ ]; 29 + "alarmdecoder" = ps: with ps; [ ]; 30 + "sensor.alpha_vantage" = ps: with ps; [ ]; 31 + "amcrest" = ps: with ps; [ ]; 32 + "media_player.anthemav" = ps: with ps; [ ]; 33 + "apcupsd" = ps: with ps; [ ]; 34 + "notify.apns" = ps: with ps; [ ]; 35 + "asterisk_mbox" = ps: with ps; [ ]; 36 + "light.avion" = ps: with ps; [ ]; 37 + "axis" = ps: with ps; [ ]; 38 + "tts.baidu" = ps: with ps; [ ]; 39 + "sensor.modem_callerid" = ps: with ps; [ ]; 40 + "sensor.linux_battery" = ps: with ps; [ batinfo ]; 41 + "sensor.eddystone_temperature" = ps: with ps; [ ]; 42 + "device_tracker.linksys_ap" = ps: with ps; [ beautifulsoup4 ]; 43 + "sensor.geizhals" = ps: with ps; [ beautifulsoup4 ]; 44 + "sensor.scrape" = ps: with ps; [ beautifulsoup4 ]; 45 + "sensor.sytadin" = ps: with ps; [ beautifulsoup4 ]; 46 + "zha" = ps: with ps; [ ]; 47 + "blink" = ps: with ps; [ ]; 48 + "light.blinksticklight" = ps: with ps; [ BlinkStick ]; 49 + "light.blinkt" = ps: with ps; [ ]; 50 + "sensor.bitcoin" = ps: with ps; [ ]; 51 + "light.decora" = ps: with ps; [ ]; 52 + "sensor.bme680" = ps: with ps; [ ]; 53 + "notify.aws_lambda" = ps: with ps; [ boto3 ]; 54 + "notify.aws_sns" = ps: with ps; [ boto3 ]; 55 + "notify.aws_sqs" = ps: with ps; [ boto3 ]; 56 + "tts.amazon_polly" = ps: with ps; [ boto3 ]; 57 + "sensor.broadlink" = ps: with ps; [ ]; 58 + "switch.broadlink" = ps: with ps; [ ]; 59 + "sensor.buienradar" = ps: with ps; [ ]; 60 + "weather.buienradar" = ps: with ps; [ ]; 61 + "calendar.caldav" = ps: with ps; [ ]; 62 + "notify.ciscospark" = ps: with ps; [ ]; 63 + "coinbase" = ps: with ps; [ ]; 64 + "sensor.coinmarketcap" = ps: with ps; [ ]; 65 + "alarm_control_panel.concord232" = ps: with ps; [ ]; 66 + "binary_sensor.concord232" = ps: with ps; [ ]; 67 + "sensor.crimereports" = ps: with ps; [ ]; 68 + "datadog" = ps: with ps; [ datadog ]; 69 + "sensor.metoffice" = ps: with ps; [ ]; 70 + "weather.metoffice" = ps: with ps; [ ]; 71 + "light.decora_wifi" = ps: with ps; [ ]; 72 + "device_tracker.upc_connect" = ps: with ps; [ defusedxml ]; 73 + "sensor.deluge" = ps: with ps; [ ]; 74 + "switch.deluge" = ps: with ps; [ ]; 75 + "media_player.denonavr" = ps: with ps; [ ]; 76 + "media_player.directv" = ps: with ps; [ ]; 77 + "sensor.discogs" = ps: with ps; [ discogs_client ]; 78 + "notify.discord" = ps: with ps; [ ]; 79 + "updater" = ps: with ps; [ distro ]; 80 + "switch.digitalloggers" = ps: with ps; [ ]; 81 + "notify.xmpp" = ps: with ps; [ pyasn1-modules pyasn1 sleekxmpp ]; 82 + "sensor.dovado" = ps: with ps; [ ]; 83 + "sensor.dsmr" = ps: with ps; [ ]; 84 + "dweet" = ps: with ps; [ ]; 85 + "sensor.dweet" = ps: with ps; [ ]; 86 + "sensor.eliqonline" = ps: with ps; [ ]; 87 + "enocean" = ps: with ps; [ ]; 88 + "sensor.envirophat" = ps: with ps; [ ]; 89 + "sensor.season" = ps: with ps; [ ephem ]; 90 + "keyboard_remote" = ps: with ps; [ ]; 91 + "climate.honeywell" = ps: with ps; [ ]; 92 + "image_processing.dlib_face_detect" = ps: with ps; [ ]; 93 + "image_processing.dlib_face_identify" = ps: with ps; [ ]; 94 + "sensor.fastdotcom" = ps: with ps; [ ]; 95 + "sensor.fedex" = ps: with ps; [ ]; 96 + "feedreader" = ps: with ps; [ feedparser ]; 97 + "sensor.geo_rss_events" = ps: with ps; [ feedparser ]; 98 + "sensor.fitbit" = ps: with ps; [ ]; 99 + "sensor.fixer" = ps: with ps; [ ]; 100 + "light.flux_led" = ps: with ps; [ ]; 101 + "notify.free_mobile" = ps: with ps; [ ]; 102 + "device_tracker.fritz" = ps: with ps; [ ]; 103 + "sensor.fritzbox_callmonitor" = ps: with ps; [ ]; 104 + "sensor.fritzbox_netmonitor" = ps: with ps; [ ]; 105 + "switch.fritzdect" = ps: with ps; [ ]; 106 + "media_player.frontier_silicon" = ps: with ps; [ ]; 107 + "conversation" = ps: with ps; [ ]; 108 + "tts.google" = ps: with ps; [ ]; 109 + "device_tracker.bluetooth_le_tracker" = ps: with ps; [ ]; 110 + "sensor.gearbest" = ps: with ps; [ ]; 111 + "sensor.gitter" = ps: with ps; [ ]; 112 + "notify.gntp" = ps: with ps; [ ]; 113 + "google" = ps: with ps; [ google_api_python_client oauth2client ]; 114 + "sensor.google_travel_time" = ps: with ps; [ ]; 115 + "sensor.gpsd" = ps: with ps; [ ]; 116 + "light.greenwave" = ps: with ps; [ ]; 117 + "media_player.gstreamer" = ps: with ps; [ ]; 118 + "ffmpeg" = ps: with ps; [ ]; 119 + "media_player.philips_js" = ps: with ps; [ ]; 120 + "mqtt.server" = ps: with ps; [ hbmqtt ]; 121 + "climate.heatmiser" = ps: with ps; [ ]; 122 + "switch.hikvisioncam" = ps: with ps; [ ]; 123 + "notify.hipchat" = ps: with ps; [ ]; 124 + "binary_sensor.workday" = ps: with ps; [ ]; 125 + "frontend" = ps: with ps; [ user-agents ]; 126 + "camera.onvif" = ps: with ps; [ ]; 127 + "sensor.dht" = ps: with ps; [ ]; 128 + "media_player.braviatv" = ps: with ps; [ ]; 129 + "media_player.spotify" = ps: with ps; [ ]; 130 + "netatmo" = ps: with ps; [ ]; 131 + "neato" = ps: with ps; [ ]; 132 + "sensor.sabnzbd" = ps: with ps; [ ]; 133 + "switch.anel_pwrctrl" = ps: with ps; [ ]; 134 + "switch.edimax" = ps: with ps; [ ]; 135 + "sensor.gtfs" = ps: with ps; [ ]; 136 + "binary_sensor.flic" = ps: with ps; [ ]; 137 + "media_player.lg_netcast" = ps: with ps; [ ]; 138 + "sensor.bh1750" = ps: with ps; [ ]; 139 + "sensor.bme280" = ps: with ps; [ ]; 140 + "sensor.htu21d" = ps: with ps; [ ]; 141 + "light.iglo" = ps: with ps; [ ]; 142 + "ihc" = ps: with ps; [ ]; 143 + "influxdb" = ps: with ps; [ influxdb ]; 144 + "sensor.influxdb" = ps: with ps; [ influxdb ]; 145 + "insteon_local" = ps: with ps; [ ]; 146 + "insteon_plm" = ps: with ps; [ ]; 147 + "verisure" = ps: with ps; [ ]; 148 + "media_player.kodi" = ps: with ps; [ ]; 149 + "notify.kodi" = ps: with ps; [ ]; 150 + "device_tracker.owntracks" = ps: with ps; [ libnacl ]; 151 + "device_tracker.owntracks_http" = ps: with ps; [ libnacl ]; 152 + "dyson" = ps: with ps; [ ]; 153 + "camera.foscam" = ps: with ps; [ ]; 154 + "device_tracker.mikrotik" = ps: with ps; [ ]; 155 + "media_player.soundtouch" = ps: with ps; [ libsoundtouch ]; 156 + "light.lifx_legacy" = ps: with ps; [ ]; 157 + "light.osramlightify" = ps: with ps; [ ]; 158 + "light.limitlessled" = ps: with ps; [ ]; 159 + "linode" = ps: with ps; [ linode-api ]; 160 + "media_player.liveboxplaytv" = ps: with ps; [ ]; 161 + "lametric" = ps: with ps; [ ]; 162 + "notify.lametric" = ps: with ps; [ ]; 163 + "sensor.luftdaten" = ps: with ps; [ ]; 164 + "sensor.lyft" = ps: with ps; [ ]; 165 + "notify.matrix" = ps: with ps; [ matrix-client ]; 166 + "maxcube" = ps: with ps; [ ]; 167 + "notify.message_bird" = ps: with ps; [ ]; 168 + "sensor.mfi" = ps: with ps; [ ]; 169 + "switch.mfi" = ps: with ps; [ ]; 170 + "sensor.miflora" = ps: with ps; [ ]; 171 + "upnp" = ps: with ps; [ ]; 172 + "sensor.mopar" = ps: with ps; [ ]; 173 + "tts" = ps: with ps; [ mutagen ]; 174 + "mychevy" = ps: with ps; [ ]; 175 + "mycroft" = ps: with ps; [ ]; 176 + "usps" = ps: with ps; [ ]; 177 + "media_player.nad" = ps: with ps; [ ]; 178 + "media_player.nadtcp" = ps: with ps; [ ]; 179 + "discovery" = ps: with ps; [ netdisco ]; 180 + "sensor.neurio_energy" = ps: with ps; [ ]; 181 + "sensor.nederlandse_spoorwegen" = ps: with ps; [ ]; 182 + "nuheat" = ps: with ps; [ ]; 183 + "binary_sensor.trend" = ps: with ps; [ numpy ]; 184 + "image_processing.opencv" = ps: with ps; [ numpy ]; 185 + "climate.oem" = ps: with ps; [ ]; 186 + "media_player.onkyo" = ps: with ps; [ ]; 187 + "sensor.openevse" = ps: with ps; [ ]; 188 + "media_player.openhome" = ps: with ps; [ ]; 189 + "switch.orvibo" = ps: with ps; [ ]; 190 + "mqtt" = ps: with ps; [ paho-mqtt ]; 191 + "shiftr" = ps: with ps; [ paho-mqtt ]; 192 + "media_player.panasonic_viera" = ps: with ps; [ ]; 193 + "media_player.dunehd" = ps: with ps; [ ]; 194 + "device_tracker.aruba" = ps: with ps; [ pexpect ]; 195 + "device_tracker.asuswrt" = ps: with ps; [ pexpect ]; 196 + "device_tracker.cisco_ios" = ps: with ps; [ pexpect ]; 197 + "device_tracker.unifi_direct" = ps: with ps; [ pexpect ]; 198 + "media_player.pandora" = ps: with ps; [ pexpect ]; 199 + "hue" = ps: with ps; [ ]; 200 + "rpi_pfio" = ps: with ps; [ ]; 201 + "light.piglow" = ps: with ps; [ ]; 202 + "pilight" = ps: with ps; [ ]; 203 + "dominos" = ps: with ps; [ ]; 204 + "media_player.plex" = ps: with ps; [ ]; 205 + "sensor.plex" = ps: with ps; [ ]; 206 + "sensor.mhz19" = ps: with ps; [ ]; 207 + "sensor.serial_pm" = ps: with ps; [ ]; 208 + "sensor.pocketcasts" = ps: with ps; [ ]; 209 + "climate.proliphix" = ps: with ps; [ ]; 210 + "prometheus" = ps: with ps; [ ]; 211 + "sensor.systemmonitor" = ps: with ps; [ psutil ]; 212 + "wink" = ps: with ps; [ ]; 213 + "notify.pushbullet" = ps: with ps; [ pushbullet ]; 214 + "sensor.pushbullet" = ps: with ps; [ pushbullet ]; 215 + "notify.pushetta" = ps: with ps; [ ]; 216 + "light.rpi_gpio_pwm" = ps: with ps; [ ]; 217 + "canary" = ps: with ps; [ ]; 218 + "sensor.cpuspeed" = ps: with ps; [ ]; 219 + "camera.synology" = ps: with ps; [ ]; 220 + "hdmi_cec" = ps: with ps; [ ]; 221 + "light.tplink" = ps: with ps; [ ]; 222 + "switch.tplink" = ps: with ps; [ ]; 223 + "rfxtrx" = ps: with ps; [ ]; 224 + "sensor.tibber" = ps: with ps; [ ]; 225 + "switch.dlink" = ps: with ps; [ ]; 226 + "ads" = ps: with ps; [ ]; 227 + "sensor.airvisual" = ps: with ps; [ ]; 228 + "alarm_control_panel.alarmdotcom" = ps: with ps; [ ]; 229 + "arlo" = ps: with ps; [ ]; 230 + "apple_tv" = ps: with ps; [ ]; 231 + "device_tracker.bbox" = ps: with ps; [ ]; 232 + "sensor.bbox" = ps: with ps; [ ]; 233 + "device_tracker.bluetooth_tracker" = ps: with ps; [ ]; 234 + "media_player.cast" = ps: with ps; [ PyChromecast ]; 235 + "media_player.cmus" = ps: with ps; [ ]; 236 + "comfoconnect" = ps: with ps; [ ]; 237 + "tts.microsoft" = ps: with ps; [ ]; 238 + "sensor.cups" = ps: with ps; [ ]; 239 + "daikin" = ps: with ps; [ ]; 240 + "climate.daikin" = ps: with ps; [ ]; 241 + "deconz" = ps: with ps; [ ]; 242 + "zwave" = ps: with ps; [ pydispatcher ]; 243 + "android_ip_webcam" = ps: with ps; [ ]; 244 + "sensor.ebox" = ps: with ps; [ ]; 245 + "climate.econet" = ps: with ps; [ ]; 246 + "eight_sleep" = ps: with ps; [ ]; 247 + "media_player.emby" = ps: with ps; [ ]; 248 + "envisalink" = ps: with ps; [ ]; 249 + "climate.ephember" = ps: with ps; [ ]; 250 + "sensor.fido" = ps: with ps; [ ]; 251 + "climate.flexit" = ps: with ps; [ ]; 252 + "ifttt" = ps: with ps; [ ]; 253 + "remote.harmony" = ps: with ps; [ ]; 254 + "binary_sensor.hikvision" = ps: with ps; [ ]; 255 + "hive" = ps: with ps; [ ]; 256 + "homematic" = ps: with ps; [ pyhomematic ]; 257 + "sensor.hydroquebec" = ps: with ps; [ ]; 258 + "alarm_control_panel.ialarm" = ps: with ps; [ ]; 259 + "device_tracker.icloud" = ps: with ps; [ ]; 260 + "sensor.irish_rail_transport" = ps: with ps; [ ]; 261 + "binary_sensor.iss" = ps: with ps; [ ]; 262 + "remote.itach" = ps: with ps; [ ]; 263 + "kira" = ps: with ps; [ ]; 264 + "sensor.kwb" = ps: with ps; [ ]; 265 + "sensor.lacrosse" = ps: with ps; [ ]; 266 + "sensor.lastfm" = ps: with ps; [ pylast ]; 267 + "media_player.webostv" = ps: with ps; [ websockets ]; 268 + "notify.webostv" = ps: with ps; [ ]; 269 + "litejet" = ps: with ps; [ ]; 270 + "sensor.loopenergy" = ps: with ps; [ ]; 271 + "lutron_caseta" = ps: with ps; [ ]; 272 + "lutron" = ps: with ps; [ ]; 273 + "notify.mailgun" = ps: with ps; [ ]; 274 + "mochad" = ps: with ps; [ ]; 275 + "modbus" = ps: with ps; [ ]; 276 + "media_player.monoprice" = ps: with ps; [ ]; 277 + "media_player.yamaha_musiccast" = ps: with ps; [ ]; 278 + "cover.myq" = ps: with ps; [ ]; 279 + "mysensors" = ps: with ps; [ ]; 280 + "lock.nello" = ps: with ps; [ ]; 281 + "device_tracker.netgear" = ps: with ps; [ ]; 282 + "switch.netio" = ps: with ps; [ ]; 283 + "lock.nuki" = ps: with ps; [ ]; 284 + "sensor.nut" = ps: with ps; [ ]; 285 + "alarm_control_panel.nx584" = ps: with ps; [ ]; 286 + "binary_sensor.nx584" = ps: with ps; [ ]; 287 + "iota" = ps: with ps; [ ]; 288 + "sensor.otp" = ps: with ps; [ ]; 289 + "sensor.openweathermap" = ps: with ps; [ ]; 290 + "weather.openweathermap" = ps: with ps; [ ]; 291 + "qwikswitch" = ps: with ps; [ ]; 292 + "rainbird" = ps: with ps; [ ]; 293 + "climate.sensibo" = ps: with ps; [ ]; 294 + "sensor.serial" = ps: with ps; [ ]; 295 + "switch.acer_projector" = ps: with ps; [ pyserial ]; 296 + "lock.sesame" = ps: with ps; [ ]; 297 + "sensor.sma" = ps: with ps; [ ]; 298 + "device_tracker.snmp" = ps: with ps; [ pysnmp ]; 299 + "sensor.snmp" = ps: with ps; [ pysnmp ]; 300 + "switch.snmp" = ps: with ps; [ pysnmp ]; 301 + "sensor.thinkingcleaner" = ps: with ps; [ ]; 302 + "switch.thinkingcleaner" = ps: with ps; [ ]; 303 + "sensor.blockchain" = ps: with ps; [ ]; 304 + "media_player.clementine" = ps: with ps; [ ]; 305 + "digital_ocean" = ps: with ps; [ digital-ocean ]; 306 + "ecobee" = ps: with ps; [ ]; 307 + "climate.eq3btsmart" = ps: with ps; [ ]; 308 + "sensor.etherscan" = ps: with ps; [ ]; 309 + "sensor.darksky" = ps: with ps; [ ]; 310 + "weather.darksky" = ps: with ps; [ ]; 311 + "gc100" = ps: with ps; [ ]; 312 + "sensor.hp_ilo" = ps: with ps; [ ]; 313 + "joaoapps_join" = ps: with ps; [ ]; 314 + "notify.joaoapps_join" = ps: with ps; [ ]; 315 + "juicenet" = ps: with ps; [ ]; 316 + "lirc" = ps: with ps; [ ]; 317 + "fan.xiaomi_miio" = ps: with ps; [ ]; 318 + "light.xiaomi_miio" = ps: with ps; [ ]; 319 + "switch.xiaomi_miio" = ps: with ps; [ ]; 320 + "vacuum.xiaomi_miio" = ps: with ps; [ ]; 321 + "media_player.mpd" = ps: with ps; [ ]; 322 + "light.mystrom" = ps: with ps; [ ]; 323 + "switch.mystrom" = ps: with ps; [ ]; 324 + "nest" = ps: with ps; [ ]; 325 + "device_tracker.nmap_tracker" = ps: with ps; [ ]; 326 + "notify.pushover" = ps: with ps; [ ]; 327 + "sensor.ripple" = ps: with ps; [ ]; 328 + "media_player.roku" = ps: with ps; [ ]; 329 + "sensor.sochain" = ps: with ps; [ ]; 330 + "sensor.synologydsm" = ps: with ps; [ ]; 331 + "tado" = ps: with ps; [ ]; 332 + "telegram_bot" = ps: with ps; [ ]; 333 + "sensor.twitch" = ps: with ps; [ ]; 334 + "velbus" = ps: with ps; [ ]; 335 + "media_player.vlc" = ps: with ps; [ ]; 336 + "sensor.swiss_public_transport" = ps: with ps; [ ]; 337 + "alarm_control_panel.egardia" = ps: with ps; [ ]; 338 + "sensor.whois" = ps: with ps; [ ]; 339 + "device_tracker.tile" = ps: with ps; [ ]; 340 + "climate.touchline" = ps: with ps; [ ]; 341 + "device_tracker.trackr" = ps: with ps; [ ]; 342 + "tradfri" = ps: with ps; [ ]; 343 + "device_tracker.unifi" = ps: with ps; [ ]; 344 + "keyboard" = ps: with ps; [ ]; 345 + "vera" = ps: with ps; [ ]; 346 + "media_player.vizio" = ps: with ps; [ ]; 347 + "velux" = ps: with ps; [ ]; 348 + "wemo" = ps: with ps; [ ]; 349 + "camera.xeoma" = ps: with ps; [ ]; 350 + "zabbix" = ps: with ps; [ ]; 351 + "sensor.qnap" = ps: with ps; [ ]; 352 + "switch.rachio" = ps: with ps; [ ]; 353 + "climate.radiotherm" = ps: with ps; [ ]; 354 + "raincloud" = ps: with ps; [ ]; 355 + "raspihats" = ps: with ps; [ ]; 356 + "switch.rainmachine" = ps: with ps; [ ]; 357 + "python_script" = ps: with ps; [ ]; 358 + "rflink" = ps: with ps; [ ]; 359 + "ring" = ps: with ps; [ ]; 360 + "notify.rocketchat" = ps: with ps; [ ]; 361 + "vacuum.roomba" = ps: with ps; [ ]; 362 + "switch.rpi_rf" = ps: with ps; [ ]; 363 + "media_player.russound_rnet" = ps: with ps; [ ]; 364 + "media_player.russound_rio" = ps: with ps; [ ]; 365 + "media_player.yamaha" = ps: with ps; [ ]; 366 + "media_player.samsungtv" = ps: with ps; [ ]; 367 + "satel_integra" = ps: with ps; [ ]; 368 + "sensor.deutsche_bahn" = ps: with ps; [ ]; 369 + "scsgate" = ps: with ps; [ ]; 370 + "notify.sendgrid" = ps: with ps; [ ]; 371 + "light.sensehat" = ps: with ps; [ ]; 372 + "sensor.sensehat" = ps: with ps; [ ]; 373 + "media_player.aquostv" = ps: with ps; [ ]; 374 + "sensor.shodan" = ps: with ps; [ ]; 375 + "notify.simplepush" = ps: with ps; [ ]; 376 + "alarm_control_panel.simplisafe" = ps: with ps; [ ]; 377 + "skybell" = ps: with ps; [ ]; 378 + "notify.slack" = ps: with ps; [ ]; 379 + "sleepiq" = ps: with ps; [ ]; 380 + "media_player.snapcast" = ps: with ps; [ ]; 381 + "sensor.speedtest" = ps: with ps; [ ]; 382 + "recorder" = ps: with ps; [ sqlalchemy ]; 383 + "statsd" = ps: with ps; [ statsd ]; 384 + "sensor.steam_online" = ps: with ps; [ ]; 385 + "tahoma" = ps: with ps; [ ]; 386 + "sensor.tank_utility" = ps: with ps; [ ]; 387 + "binary_sensor.tapsaff" = ps: with ps; [ ]; 388 + "tellstick" = ps: with ps; [ ]; 389 + "tellduslive" = ps: with ps; [ ]; 390 + "sensor.temper" = ps: with ps; [ ]; 391 + "tesla" = ps: with ps; [ ]; 392 + "thingspeak" = ps: with ps; [ ]; 393 + "light.tikteck" = ps: with ps; [ ]; 394 + "calendar.todoist" = ps: with ps; [ todoist ]; 395 + "toon" = ps: with ps; [ ]; 396 + "alarm_control_panel.totalconnect" = ps: with ps; [ ]; 397 + "sensor.transmission" = ps: with ps; [ transmissionrpc ]; 398 + "switch.transmission" = ps: with ps; [ transmissionrpc ]; 399 + "twilio" = ps: with ps; [ twilio ]; 400 + "sensor.uber" = ps: with ps; [ ]; 401 + "sensor.ups" = ps: with ps; [ ]; 402 + "camera.uvc" = ps: with ps; [ ]; 403 + "climate.venstar" = ps: with ps; [ ]; 404 + "volvooncall" = ps: with ps; [ ]; 405 + "sensor.vasttrafik" = ps: with ps; [ ]; 406 + "vultr" = ps: with ps; [ vultr ]; 407 + "wake_on_lan" = ps: with ps; [ ]; 408 + "switch.wake_on_lan" = ps: with ps; [ ]; 409 + "sensor.waqi" = ps: with ps; [ ]; 410 + "cloud" = ps: with ps; [ ]; 411 + "waterfurnace" = ps: with ps; [ ]; 412 + "media_player.gpmdp" = ps: with ps; [ ]; 413 + "spc" = ps: with ps; [ websockets ]; 414 + "zigbee" = ps: with ps; [ ]; 415 + "sensor.xbox_live" = ps: with ps; [ ]; 416 + "knx" = ps: with ps; [ ]; 417 + "media_player.bluesound" = ps: with ps; [ xmltodict ]; 418 + "sensor.swiss_hydrological_data" = ps: with ps; [ xmltodict ]; 419 + "sensor.ted5000" = ps: with ps; [ xmltodict ]; 420 + "sensor.yr" = ps: with ps; [ xmltodict ]; 421 + "sensor.yahoo_finance" = ps: with ps; [ ]; 422 + "sensor.yweather" = ps: with ps; [ ]; 423 + "weather.yweather" = ps: with ps; [ ]; 424 + "light.yeelight" = ps: with ps; [ ]; 425 + "light.yeelightsunflower" = ps: with ps; [ ]; 426 + "media_extractor" = ps: with ps; [ ]; 427 + "light.zengge" = ps: with ps; [ ]; 428 + "zeroconf" = ps: with ps; [ zeroconf ]; 429 + "media_player.ziggo_mediabox_xl" = ps: with ps; [ ]; 430 + }; 431 + }
+16 -4
pkgs/servers/home-assistant/default.nix
··· 1 1 { stdenv, fetchFromGitHub, python3 2 + , extraComponents ? [] 2 3 , extraPackages ? ps: [] 3 4 , skipPip ? true }: 4 5 ··· 24 25 }; 25 26 }; 26 27 28 + componentPackages = import ./component-packages.nix; 29 + 30 + availableComponents = builtins.attrNames componentPackages.components; 31 + 32 + getPackages = component: builtins.getAttr component componentPackages.components; 33 + 34 + componentBuildInputs = map (component: getPackages component py.pkgs) extraComponents; 35 + 27 36 # Ensure that we are using a consistent package set 28 37 extraBuildInputs = extraPackages py.pkgs; 29 38 39 + # Don't forget to run parse-requirements.py after updating 40 + hassVersion = "0.62.1"; 41 + 30 42 in with py.pkgs; buildPythonApplication rec { 31 43 pname = "homeassistant"; 32 - version = "0.62.1"; 44 + version = assert (componentPackages.version == hassVersion); hassVersion; 33 45 34 - diabled = !isPy3k; 46 + inherit availableComponents; 35 47 36 48 # PyPI tarball is missing tests/ directory 37 49 src = fetchFromGitHub { ··· 45 57 # From setup.py 46 58 requests pyyaml pytz pip jinja2 voluptuous typing aiohttp yarl async-timeout chardet astral certifi 47 59 # From the components that are part of the default configuration.yaml 48 - sqlalchemy aiohttp-cors hass-frontend user-agents distro mutagen xmltodict netdisco 49 - ] ++ extraBuildInputs; 60 + sqlalchemy aiohttp-cors hass-frontend user-agents distro mutagen xmltodict netdisco 61 + ] ++ componentBuildInputs ++ extraBuildInputs; 50 62 51 63 checkInputs = [ 52 64 pytest requests-mock pydispatcher pytest-aiohttp
+97
pkgs/servers/home-assistant/parse-requirements.py
··· 1 + #! /usr/bin/env nix-shell 2 + #! nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ setuptools ])" 3 + # 4 + # This script downloads https://github.com/home-assistant/home-assistant/blob/master/requirements_all.txt. 5 + # This file contains lines of the form 6 + # 7 + # # homeassistant.components.foo 8 + # # homeassistant.components.bar 9 + # foobar==1.2.3 10 + # 11 + # i.e. it lists dependencies and the components that require them. 12 + # By parsing the file, a dictionary mapping component to dependencies is created. 13 + # For all of these dependencies, Nixpkgs' python3Packages are searched for appropriate names. 14 + # Then, a Nix attribute set mapping component name to dependencies is created. 15 + 16 + from urllib.request import urlopen 17 + import subprocess 18 + import os 19 + import sys 20 + import json 21 + import re 22 + from pkg_resources import Requirement, RequirementParseError 23 + 24 + PREFIX = '# homeassistant.components.' 25 + PKG_SET = 'python3Packages' 26 + 27 + def get_version(): 28 + with open(os.path.dirname(sys.argv[0]) + '/default.nix') as f: 29 + m = re.search('hassVersion = "([\\d\\.]+)";', f.read()) 30 + return m.group(1) 31 + 32 + def fetch_reqs(version='master'): 33 + requirements = {} 34 + with urlopen('https://github.com/home-assistant/home-assistant/raw/{}/requirements_all.txt'.format(version)) as response: 35 + components = [] 36 + for line in response.read().decode().splitlines(): 37 + if line == '': 38 + components = [] 39 + elif line[:len(PREFIX)] == PREFIX: 40 + component = line[len(PREFIX):] 41 + components.append(component) 42 + if component not in requirements: 43 + requirements[component] = [] 44 + elif line[0] != '#': 45 + for component in components: 46 + requirements[component].append(line) 47 + return requirements 48 + 49 + # Store a JSON dump of Nixpkgs' python3Packages 50 + output = subprocess.check_output(['nix-env', '-f', os.path.dirname(sys.argv[0]) + '/../../..', '-qa', '-A', PKG_SET, '--json']) 51 + packages = json.loads(output) 52 + 53 + def name_to_attr_path(req): 54 + attr_paths = [] 55 + pattern = re.compile('python3\\.6-{}-\\d'.format(req), re.I) 56 + for attr_path, package in packages.items(): 57 + if pattern.match(package['name']): 58 + attr_paths.append(attr_path) 59 + # Let's hope there's only one derivation with a matching name 60 + assert(len(attr_paths) <= 1) 61 + if attr_paths: 62 + return attr_paths[0] 63 + else: 64 + return None 65 + 66 + version = get_version() 67 + requirements = fetch_reqs(version=version) 68 + build_inputs = {} 69 + for component, reqs in requirements.items(): 70 + attr_paths = [] 71 + for req in reqs: 72 + try: 73 + name = Requirement.parse(req).project_name 74 + attr_path = name_to_attr_path(name) 75 + if attr_path is not None: 76 + # Add attribute path without "python3Packages." prefix 77 + attr_paths.append(attr_path[len(PKG_SET + '.'):]) 78 + except RequirementParseError: 79 + continue 80 + else: 81 + build_inputs[component] = attr_paths 82 + 83 + # Only select components which have any dependency 84 + #build_inputs = {k: v for k, v in build_inputs.items() if len(v) > 0} 85 + 86 + with open(os.path.dirname(sys.argv[0]) + '/component-packages.nix', 'w') as f: 87 + f.write('# Generated from parse-requirements.py\n') 88 + f.write('# Do not edit!\n\n') 89 + f.write('{\n') 90 + f.write(' version = "{}";\n'.format(version)) 91 + f.write(' components = {\n') 92 + for component, attr_paths in build_inputs.items(): 93 + f.write(' "{}" = ps: with ps; [ '.format(component)) 94 + f.write(' '.join(attr_paths)) 95 + f.write(' ];\n') 96 + f.write(' };\n') 97 + f.write('}\n')