home-assistant: compute extraComponents from config

wip/yesman
Robert Schütz 6 years ago
parent 356b553239
commit 78c2ca326e
  1. 36
      nixos/modules/services/misc/home-assistant.nix
  2. 7
      nixos/tests/home-assistant.nix
  3. 431
      pkgs/servers/home-assistant/component-packages.nix
  4. 20
      pkgs/servers/home-assistant/default.nix
  5. 97
      pkgs/servers/home-assistant/parse-requirements.py

@ -6,6 +6,19 @@ let
cfg = config.services.home-assistant;
configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config);
availableComponents = pkgs.home-assistant.availableComponents;
# Returns whether component is used in config
useComponent = component: hasAttrByPath (splitString "." component) cfg.config;
# List of components used in config
extraComponents = filter useComponent availableComponents;
package = if cfg.autoExtraComponents
then (cfg.package.override { inherit extraComponents; })
else cfg.package;
in {
meta.maintainers = with maintainers; [ dotlambda ];
@ -29,6 +42,7 @@ in {
};
frontend = { };
http = { };
feedreader.urls = [ "https://nixos.org/blogs.xml" ];
}
'';
description = ''
@ -48,10 +62,22 @@ in {
'';
description = ''
Home Assistant package to use.
Most Home Assistant components require additional dependencies,
which are best specified by overriding <literal>pkgs.home-assistant</literal>.
You can find the dependencies by searching for failed imports in your log or by looking at this list:
<link xlink:href="https://github.com/home-assistant/home-assistant/blob/master/requirements_all.txt"/>
Override <literal>extraPackages</literal> in order to add additional dependencies.
'';
};
autoExtraComponents = mkOption {
default = true;
type = types.bool;
description = ''
If set to <literal>true</literal>, the components used in <literal>config</config>
are set as the specified package's <literal>extraComponents</literal>.
This in turn adds all packaged dependencies to the derivation.
You might still see import errors in your log.
In this case, you will need to package the necessary dependencies yourself
or ask for someone else to package them.
If a dependency is packaged but not automatically added to this list,
you might need to specify it in <literal>extraPackages</literal>.
'';
};
};
@ -67,7 +93,7 @@ in {
'';
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/hass --config "${cfg.configDir}"
${package}/bin/hass --config "${cfg.configDir}"
'';
User = "hass";
Group = "hass";

@ -17,13 +17,16 @@ in {
homeassistant = {
name = "Home";
time_zone = "UTC";
latitude = "0.0";
longitude = "0.0";
elevation = 0;
};
frontend = { };
http = { };
};
};
};
};
};
testScript = ''
startAll;
@ -37,5 +40,7 @@ in {
$hass->waitForOpenPort(8123);
$hass->succeed("curl --fail http://localhost:8123/states");
$hass->succeed("curl --fail http://localhost:8123/api/ | grep 'API running'");
$hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR");
'';
})

@ -0,0 +1,431 @@
# Generated from parse-requirements.py
# Do not edit!
{
version = "0.62.1";
components = {
"nuimo_controller" = ps: with ps; [ ];
"bbb_gpio" = ps: with ps; [ ];
"doorbird" = ps: with ps; [ ];
"isy994" = ps: with ps; [ ];
"notify.html5" = ps: with ps; [ pyjwt ];
"sensor.mvglive" = ps: with ps; [ ];
"arduino" = ps: with ps; [ ];
"xiaomi_aqara" = ps: with ps; [ ];
"rpi_gpio" = ps: with ps; [ ];
"remember_the_milk" = ps: with ps; [ httplib2 ];
"media_player.sonos" = ps: with ps; [ ];
"sensor.travisci" = ps: with ps; [ ];
"notify.twitter" = ps: with ps; [ ];
"notify.yessssms" = ps: with ps; [ ];
"abode" = ps: with ps; [ ];
"device_tracker.automatic" = ps: with ps; [ ];
"sensor.dnsip" = ps: with ps; [ aiodns ];
"emulated_hue" = ps: with ps; [ aiohttp-cors ];
"http" = ps: with ps; [ aiohttp-cors ];
"sensor.imap" = ps: with ps; [ ];
"light.lifx" = ps: with ps; [ ];
"scene.hunterdouglas_powerview" = ps: with ps; [ ];
"alarmdecoder" = ps: with ps; [ ];
"sensor.alpha_vantage" = ps: with ps; [ ];
"amcrest" = ps: with ps; [ ];
"media_player.anthemav" = ps: with ps; [ ];
"apcupsd" = ps: with ps; [ ];
"notify.apns" = ps: with ps; [ ];
"asterisk_mbox" = ps: with ps; [ ];
"light.avion" = ps: with ps; [ ];
"axis" = ps: with ps; [ ];
"tts.baidu" = ps: with ps; [ ];
"sensor.modem_callerid" = ps: with ps; [ ];
"sensor.linux_battery" = ps: with ps; [ batinfo ];
"sensor.eddystone_temperature" = ps: with ps; [ ];
"device_tracker.linksys_ap" = ps: with ps; [ beautifulsoup4 ];
"sensor.geizhals" = ps: with ps; [ beautifulsoup4 ];
"sensor.scrape" = ps: with ps; [ beautifulsoup4 ];
"sensor.sytadin" = ps: with ps; [ beautifulsoup4 ];
"zha" = ps: with ps; [ ];
"blink" = ps: with ps; [ ];
"light.blinksticklight" = ps: with ps; [ BlinkStick ];
"light.blinkt" = ps: with ps; [ ];
"sensor.bitcoin" = ps: with ps; [ ];
"light.decora" = ps: with ps; [ ];
"sensor.bme680" = ps: with ps; [ ];
"notify.aws_lambda" = ps: with ps; [ boto3 ];
"notify.aws_sns" = ps: with ps; [ boto3 ];
"notify.aws_sqs" = ps: with ps; [ boto3 ];
"tts.amazon_polly" = ps: with ps; [ boto3 ];
"sensor.broadlink" = ps: with ps; [ ];
"switch.broadlink" = ps: with ps; [ ];
"sensor.buienradar" = ps: with ps; [ ];
"weather.buienradar" = ps: with ps; [ ];
"calendar.caldav" = ps: with ps; [ ];
"notify.ciscospark" = ps: with ps; [ ];
"coinbase" = ps: with ps; [ ];
"sensor.coinmarketcap" = ps: with ps; [ ];
"alarm_control_panel.concord232" = ps: with ps; [ ];
"binary_sensor.concord232" = ps: with ps; [ ];
"sensor.crimereports" = ps: with ps; [ ];
"datadog" = ps: with ps; [ datadog ];
"sensor.metoffice" = ps: with ps; [ ];
"weather.metoffice" = ps: with ps; [ ];
"light.decora_wifi" = ps: with ps; [ ];
"device_tracker.upc_connect" = ps: with ps; [ defusedxml ];
"sensor.deluge" = ps: with ps; [ ];
"switch.deluge" = ps: with ps; [ ];
"media_player.denonavr" = ps: with ps; [ ];
"media_player.directv" = ps: with ps; [ ];
"sensor.discogs" = ps: with ps; [ discogs_client ];
"notify.discord" = ps: with ps; [ ];
"updater" = ps: with ps; [ distro ];
"switch.digitalloggers" = ps: with ps; [ ];
"notify.xmpp" = ps: with ps; [ pyasn1-modules pyasn1 sleekxmpp ];
"sensor.dovado" = ps: with ps; [ ];
"sensor.dsmr" = ps: with ps; [ ];
"dweet" = ps: with ps; [ ];
"sensor.dweet" = ps: with ps; [ ];
"sensor.eliqonline" = ps: with ps; [ ];
"enocean" = ps: with ps; [ ];
"sensor.envirophat" = ps: with ps; [ ];
"sensor.season" = ps: with ps; [ ephem ];
"keyboard_remote" = ps: with ps; [ ];
"climate.honeywell" = ps: with ps; [ ];
"image_processing.dlib_face_detect" = ps: with ps; [ ];
"image_processing.dlib_face_identify" = ps: with ps; [ ];
"sensor.fastdotcom" = ps: with ps; [ ];
"sensor.fedex" = ps: with ps; [ ];
"feedreader" = ps: with ps; [ feedparser ];
"sensor.geo_rss_events" = ps: with ps; [ feedparser ];
"sensor.fitbit" = ps: with ps; [ ];
"sensor.fixer" = ps: with ps; [ ];
"light.flux_led" = ps: with ps; [ ];
"notify.free_mobile" = ps: with ps; [ ];
"device_tracker.fritz" = ps: with ps; [ ];
"sensor.fritzbox_callmonitor" = ps: with ps; [ ];
"sensor.fritzbox_netmonitor" = ps: with ps; [ ];
"switch.fritzdect" = ps: with ps; [ ];
"media_player.frontier_silicon" = ps: with ps; [ ];
"conversation" = ps: with ps; [ ];
"tts.google" = ps: with ps; [ ];
"device_tracker.bluetooth_le_tracker" = ps: with ps; [ ];
"sensor.gearbest" = ps: with ps; [ ];
"sensor.gitter" = ps: with ps; [ ];
"notify.gntp" = ps: with ps; [ ];
"google" = ps: with ps; [ google_api_python_client oauth2client ];
"sensor.google_travel_time" = ps: with ps; [ ];
"sensor.gpsd" = ps: with ps; [ ];
"light.greenwave" = ps: with ps; [ ];
"media_player.gstreamer" = ps: with ps; [ ];
"ffmpeg" = ps: with ps; [ ];
"media_player.philips_js" = ps: with ps; [ ];
"mqtt.server" = ps: with ps; [ hbmqtt ];
"climate.heatmiser" = ps: with ps; [ ];
"switch.hikvisioncam" = ps: with ps; [ ];
"notify.hipchat" = ps: with ps; [ ];
"binary_sensor.workday" = ps: with ps; [ ];
"frontend" = ps: with ps; [ user-agents ];
"camera.onvif" = ps: with ps; [ ];
"sensor.dht" = ps: with ps; [ ];
"media_player.braviatv" = ps: with ps; [ ];
"media_player.spotify" = ps: with ps; [ ];
"netatmo" = ps: with ps; [ ];
"neato" = ps: with ps; [ ];
"sensor.sabnzbd" = ps: with ps; [ ];
"switch.anel_pwrctrl" = ps: with ps; [ ];
"switch.edimax" = ps: with ps; [ ];
"sensor.gtfs" = ps: with ps; [ ];
"binary_sensor.flic" = ps: with ps; [ ];
"media_player.lg_netcast" = ps: with ps; [ ];
"sensor.bh1750" = ps: with ps; [ ];
"sensor.bme280" = ps: with ps; [ ];
"sensor.htu21d" = ps: with ps; [ ];
"light.iglo" = ps: with ps; [ ];
"ihc" = ps: with ps; [ ];
"influxdb" = ps: with ps; [ influxdb ];
"sensor.influxdb" = ps: with ps; [ influxdb ];
"insteon_local" = ps: with ps; [ ];
"insteon_plm" = ps: with ps; [ ];
"verisure" = ps: with ps; [ ];
"media_player.kodi" = ps: with ps; [ ];
"notify.kodi" = ps: with ps; [ ];
"device_tracker.owntracks" = ps: with ps; [ libnacl ];
"device_tracker.owntracks_http" = ps: with ps; [ libnacl ];
"dyson" = ps: with ps; [ ];
"camera.foscam" = ps: with ps; [ ];
"device_tracker.mikrotik" = ps: with ps; [ ];
"media_player.soundtouch" = ps: with ps; [ libsoundtouch ];
"light.lifx_legacy" = ps: with ps; [ ];
"light.osramlightify" = ps: with ps; [ ];
"light.limitlessled" = ps: with ps; [ ];
"linode" = ps: with ps; [ linode-api ];
"media_player.liveboxplaytv" = ps: with ps; [ ];
"lametric" = ps: with ps; [ ];
"notify.lametric" = ps: with ps; [ ];
"sensor.luftdaten" = ps: with ps; [ ];
"sensor.lyft" = ps: with ps; [ ];
"notify.matrix" = ps: with ps; [ matrix-client ];
"maxcube" = ps: with ps; [ ];
"notify.message_bird" = ps: with ps; [ ];
"sensor.mfi" = ps: with ps; [ ];
"switch.mfi" = ps: with ps; [ ];
"sensor.miflora" = ps: with ps; [ ];
"upnp" = ps: with ps; [ ];
"sensor.mopar" = ps: with ps; [ ];
"tts" = ps: with ps; [ mutagen ];
"mychevy" = ps: with ps; [ ];
"mycroft" = ps: with ps; [ ];
"usps" = ps: with ps; [ ];
"media_player.nad" = ps: with ps; [ ];
"media_player.nadtcp" = ps: with ps; [ ];
"discovery" = ps: with ps; [ netdisco ];
"sensor.neurio_energy" = ps: with ps; [ ];
"sensor.nederlandse_spoorwegen" = ps: with ps; [ ];
"nuheat" = ps: with ps; [ ];
"binary_sensor.trend" = ps: with ps; [ numpy ];
"image_processing.opencv" = ps: with ps; [ numpy ];
"climate.oem" = ps: with ps; [ ];
"media_player.onkyo" = ps: with ps; [ ];
"sensor.openevse" = ps: with ps; [ ];
"media_player.openhome" = ps: with ps; [ ];
"switch.orvibo" = ps: with ps; [ ];
"mqtt" = ps: with ps; [ paho-mqtt ];
"shiftr" = ps: with ps; [ paho-mqtt ];
"media_player.panasonic_viera" = ps: with ps; [ ];
"media_player.dunehd" = ps: with ps; [ ];
"device_tracker.aruba" = ps: with ps; [ pexpect ];
"device_tracker.asuswrt" = ps: with ps; [ pexpect ];
"device_tracker.cisco_ios" = ps: with ps; [ pexpect ];
"device_tracker.unifi_direct" = ps: with ps; [ pexpect ];
"media_player.pandora" = ps: with ps; [ pexpect ];
"hue" = ps: with ps; [ ];
"rpi_pfio" = ps: with ps; [ ];
"light.piglow" = ps: with ps; [ ];
"pilight" = ps: with ps; [ ];
"dominos" = ps: with ps; [ ];
"media_player.plex" = ps: with ps; [ ];
"sensor.plex" = ps: with ps; [ ];
"sensor.mhz19" = ps: with ps; [ ];
"sensor.serial_pm" = ps: with ps; [ ];
"sensor.pocketcasts" = ps: with ps; [ ];
"climate.proliphix" = ps: with ps; [ ];
"prometheus" = ps: with ps; [ ];
"sensor.systemmonitor" = ps: with ps; [ psutil ];
"wink" = ps: with ps; [ ];
"notify.pushbullet" = ps: with ps; [ pushbullet ];
"sensor.pushbullet" = ps: with ps; [ pushbullet ];
"notify.pushetta" = ps: with ps; [ ];
"light.rpi_gpio_pwm" = ps: with ps; [ ];
"canary" = ps: with ps; [ ];
"sensor.cpuspeed" = ps: with ps; [ ];
"camera.synology" = ps: with ps; [ ];
"hdmi_cec" = ps: with ps; [ ];
"light.tplink" = ps: with ps; [ ];
"switch.tplink" = ps: with ps; [ ];
"rfxtrx" = ps: with ps; [ ];
"sensor.tibber" = ps: with ps; [ ];
"switch.dlink" = ps: with ps; [ ];
"ads" = ps: with ps; [ ];
"sensor.airvisual" = ps: with ps; [ ];
"alarm_control_panel.alarmdotcom" = ps: with ps; [ ];
"arlo" = ps: with ps; [ ];
"apple_tv" = ps: with ps; [ ];
"device_tracker.bbox" = ps: with ps; [ ];
"sensor.bbox" = ps: with ps; [ ];
"device_tracker.bluetooth_tracker" = ps: with ps; [ ];
"media_player.cast" = ps: with ps; [ PyChromecast ];
"media_player.cmus" = ps: with ps; [ ];
"comfoconnect" = ps: with ps; [ ];
"tts.microsoft" = ps: with ps; [ ];
"sensor.cups" = ps: with ps; [ ];
"daikin" = ps: with ps; [ ];
"climate.daikin" = ps: with ps; [ ];
"deconz" = ps: with ps; [ ];
"zwave" = ps: with ps; [ pydispatcher ];
"android_ip_webcam" = ps: with ps; [ ];
"sensor.ebox" = ps: with ps; [ ];
"climate.econet" = ps: with ps; [ ];
"eight_sleep" = ps: with ps; [ ];
"media_player.emby" = ps: with ps; [ ];
"envisalink" = ps: with ps; [ ];
"climate.ephember" = ps: with ps; [ ];
"sensor.fido" = ps: with ps; [ ];
"climate.flexit" = ps: with ps; [ ];
"ifttt" = ps: with ps; [ ];
"remote.harmony" = ps: with ps; [ ];
"binary_sensor.hikvision" = ps: with ps; [ ];
"hive" = ps: with ps; [ ];
"homematic" = ps: with ps; [ pyhomematic ];
"sensor.hydroquebec" = ps: with ps; [ ];
"alarm_control_panel.ialarm" = ps: with ps; [ ];
"device_tracker.icloud" = ps: with ps; [ ];
"sensor.irish_rail_transport" = ps: with ps; [ ];
"binary_sensor.iss" = ps: with ps; [ ];
"remote.itach" = ps: with ps; [ ];
"kira" = ps: with ps; [ ];
"sensor.kwb" = ps: with ps; [ ];
"sensor.lacrosse" = ps: with ps; [ ];
"sensor.lastfm" = ps: with ps; [ pylast ];
"media_player.webostv" = ps: with ps; [ websockets ];
"notify.webostv" = ps: with ps; [ ];
"litejet" = ps: with ps; [ ];
"sensor.loopenergy" = ps: with ps; [ ];
"lutron_caseta" = ps: with ps; [ ];
"lutron" = ps: with ps; [ ];
"notify.mailgun" = ps: with ps; [ ];
"mochad" = ps: with ps; [ ];
"modbus" = ps: with ps; [ ];
"media_player.monoprice" = ps: with ps; [ ];
"media_player.yamaha_musiccast" = ps: with ps; [ ];
"cover.myq" = ps: with ps; [ ];
"mysensors" = ps: with ps; [ ];
"lock.nello" = ps: with ps; [ ];
"device_tracker.netgear" = ps: with ps; [ ];
"switch.netio" = ps: with ps; [ ];
"lock.nuki" = ps: with ps; [ ];
"sensor.nut" = ps: with ps; [ ];
"alarm_control_panel.nx584" = ps: with ps; [ ];
"binary_sensor.nx584" = ps: with ps; [ ];
"iota" = ps: with ps; [ ];
"sensor.otp" = ps: with ps; [ ];
"sensor.openweathermap" = ps: with ps; [ ];
"weather.openweathermap" = ps: with ps; [ ];
"qwikswitch" = ps: with ps; [ ];
"rainbird" = ps: with ps; [ ];
"climate.sensibo" = ps: with ps; [ ];
"sensor.serial" = ps: with ps; [ ];
"switch.acer_projector" = ps: with ps; [ pyserial ];
"lock.sesame" = ps: with ps; [ ];
"sensor.sma" = ps: with ps; [ ];
"device_tracker.snmp" = ps: with ps; [ pysnmp ];
"sensor.snmp" = ps: with ps; [ pysnmp ];
"switch.snmp" = ps: with ps; [ pysnmp ];
"sensor.thinkingcleaner" = ps: with ps; [ ];
"switch.thinkingcleaner" = ps: with ps; [ ];
"sensor.blockchain" = ps: with ps; [ ];
"media_player.clementine" = ps: with ps; [ ];
"digital_ocean" = ps: with ps; [ digital-ocean ];
"ecobee" = ps: with ps; [ ];
"climate.eq3btsmart" = ps: with ps; [ ];
"sensor.etherscan" = ps: with ps; [ ];
"sensor.darksky" = ps: with ps; [ ];
"weather.darksky" = ps: with ps; [ ];
"gc100" = ps: with ps; [ ];
"sensor.hp_ilo" = ps: with ps; [ ];
"joaoapps_join" = ps: with ps; [ ];
"notify.joaoapps_join" = ps: with ps; [ ];
"juicenet" = ps: with ps; [ ];
"lirc" = ps: with ps; [ ];
"fan.xiaomi_miio" = ps: with ps; [ ];
"light.xiaomi_miio" = ps: with ps; [ ];
"switch.xiaomi_miio" = ps: with ps; [ ];
"vacuum.xiaomi_miio" = ps: with ps; [ ];
"media_player.mpd" = ps: with ps; [ ];
"light.mystrom" = ps: with ps; [ ];
"switch.mystrom" = ps: with ps; [ ];
"nest" = ps: with ps; [ ];
"device_tracker.nmap_tracker" = ps: with ps; [ ];
"notify.pushover" = ps: with ps; [ ];
"sensor.ripple" = ps: with ps; [ ];
"media_player.roku" = ps: with ps; [ ];
"sensor.sochain" = ps: with ps; [ ];
"sensor.synologydsm" = ps: with ps; [ ];
"tado" = ps: with ps; [ ];
"telegram_bot" = ps: with ps; [ ];
"sensor.twitch" = ps: with ps; [ ];
"velbus" = ps: with ps; [ ];
"media_player.vlc" = ps: with ps; [ ];
"sensor.swiss_public_transport" = ps: with ps; [ ];
"alarm_control_panel.egardia" = ps: with ps; [ ];
"sensor.whois" = ps: with ps; [ ];
"device_tracker.tile" = ps: with ps; [ ];
"climate.touchline" = ps: with ps; [ ];
"device_tracker.trackr" = ps: with ps; [ ];
"tradfri" = ps: with ps; [ ];
"device_tracker.unifi" = ps: with ps; [ ];
"keyboard" = ps: with ps; [ ];
"vera" = ps: with ps; [ ];
"media_player.vizio" = ps: with ps; [ ];
"velux" = ps: with ps; [ ];
"wemo" = ps: with ps; [ ];
"camera.xeoma" = ps: with ps; [ ];
"zabbix" = ps: with ps; [ ];
"sensor.qnap" = ps: with ps; [ ];
"switch.rachio" = ps: with ps; [ ];
"climate.radiotherm" = ps: with ps; [ ];
"raincloud" = ps: with ps; [ ];
"raspihats" = ps: with ps; [ ];
"switch.rainmachine" = ps: with ps; [ ];
"python_script" = ps: with ps; [ ];
"rflink" = ps: with ps; [ ];
"ring" = ps: with ps; [ ];
"notify.rocketchat" = ps: with ps; [ ];
"vacuum.roomba" = ps: with ps; [ ];
"switch.rpi_rf" = ps: with ps; [ ];
"media_player.russound_rnet" = ps: with ps; [ ];
"media_player.russound_rio" = ps: with ps; [ ];
"media_player.yamaha" = ps: with ps; [ ];
"media_player.samsungtv" = ps: with ps; [ ];
"satel_integra" = ps: with ps; [ ];
"sensor.deutsche_bahn" = ps: with ps; [ ];
"scsgate" = ps: with ps; [ ];
"notify.sendgrid" = ps: with ps; [ ];
"light.sensehat" = ps: with ps; [ ];
"sensor.sensehat" = ps: with ps; [ ];
"media_player.aquostv" = ps: with ps; [ ];
"sensor.shodan" = ps: with ps; [ ];
"notify.simplepush" = ps: with ps; [ ];
"alarm_control_panel.simplisafe" = ps: with ps; [ ];
"skybell" = ps: with ps; [ ];
"notify.slack" = ps: with ps; [ ];
"sleepiq" = ps: with ps; [ ];
"media_player.snapcast" = ps: with ps; [ ];
"sensor.speedtest" = ps: with ps; [ ];
"recorder" = ps: with ps; [ sqlalchemy ];
"statsd" = ps: with ps; [ statsd ];
"sensor.steam_online" = ps: with ps; [ ];
"tahoma" = ps: with ps; [ ];
"sensor.tank_utility" = ps: with ps; [ ];
"binary_sensor.tapsaff" = ps: with ps; [ ];
"tellstick" = ps: with ps; [ ];
"tellduslive" = ps: with ps; [ ];
"sensor.temper" = ps: with ps; [ ];
"tesla" = ps: with ps; [ ];
"thingspeak" = ps: with ps; [ ];
"light.tikteck" = ps: with ps; [ ];
"calendar.todoist" = ps: with ps; [ todoist ];
"toon" = ps: with ps; [ ];
"alarm_control_panel.totalconnect" = ps: with ps; [ ];
"sensor.transmission" = ps: with ps; [ transmissionrpc ];
"switch.transmission" = ps: with ps; [ transmissionrpc ];
"twilio" = ps: with ps; [ twilio ];
"sensor.uber" = ps: with ps; [ ];
"sensor.ups" = ps: with ps; [ ];
"camera.uvc" = ps: with ps; [ ];
"climate.venstar" = ps: with ps; [ ];
"volvooncall" = ps: with ps; [ ];
"sensor.vasttrafik" = ps: with ps; [ ];
"vultr" = ps: with ps; [ vultr ];
"wake_on_lan" = ps: with ps; [ ];
"switch.wake_on_lan" = ps: with ps; [ ];
"sensor.waqi" = ps: with ps; [ ];
"cloud" = ps: with ps; [ ];
"waterfurnace" = ps: with ps; [ ];
"media_player.gpmdp" = ps: with ps; [ ];
"spc" = ps: with ps; [ websockets ];
"zigbee" = ps: with ps; [ ];
"sensor.xbox_live" = ps: with ps; [ ];
"knx" = ps: with ps; [ ];
"media_player.bluesound" = ps: with ps; [ xmltodict ];
"sensor.swiss_hydrological_data" = ps: with ps; [ xmltodict ];
"sensor.ted5000" = ps: with ps; [ xmltodict ];
"sensor.yr" = ps: with ps; [ xmltodict ];
"sensor.yahoo_finance" = ps: with ps; [ ];
"sensor.yweather" = ps: with ps; [ ];
"weather.yweather" = ps: with ps; [ ];
"light.yeelight" = ps: with ps; [ ];
"light.yeelightsunflower" = ps: with ps; [ ];
"media_extractor" = ps: with ps; [ ];
"light.zengge" = ps: with ps; [ ];
"zeroconf" = ps: with ps; [ zeroconf ];
"media_player.ziggo_mediabox_xl" = ps: with ps; [ ];
};
}

@ -1,4 +1,5 @@
{ stdenv, fetchFromGitHub, python3
, extraComponents ? []
, extraPackages ? ps: []
, skipPip ? true }:
@ -24,14 +25,25 @@ let
};
};
componentPackages = import ./component-packages.nix;
availableComponents = builtins.attrNames componentPackages.components;
getPackages = component: builtins.getAttr component componentPackages.components;
componentBuildInputs = map (component: getPackages component py.pkgs) extraComponents;
# Ensure that we are using a consistent package set
extraBuildInputs = extraPackages py.pkgs;
# Don't forget to run parse-requirements.py after updating
hassVersion = "0.62.1";
in with py.pkgs; buildPythonApplication rec {
pname = "homeassistant";
version = "0.62.1";
version = assert (componentPackages.version == hassVersion); hassVersion;
diabled = !isPy3k;
inherit availableComponents;
# PyPI tarball is missing tests/ directory
src = fetchFromGitHub {
@ -45,8 +57,8 @@ in with py.pkgs; buildPythonApplication rec {
# From setup.py
requests pyyaml pytz pip jinja2 voluptuous typing aiohttp yarl async-timeout chardet astral certifi
# From the components that are part of the default configuration.yaml
sqlalchemy aiohttp-cors hass-frontend user-agents distro mutagen xmltodict netdisco
] ++ extraBuildInputs;
sqlalchemy aiohttp-cors hass-frontend user-agents distro mutagen xmltodict netdisco
] ++ componentBuildInputs ++ extraBuildInputs;
checkInputs = [
pytest requests-mock pydispatcher pytest-aiohttp

@ -0,0 +1,97 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ setuptools ])"
#
# This script downloads https://github.com/home-assistant/home-assistant/blob/master/requirements_all.txt.
# This file contains lines of the form
#
# # homeassistant.components.foo
# # homeassistant.components.bar
# foobar==1.2.3
#
# i.e. it lists dependencies and the components that require them.
# By parsing the file, a dictionary mapping component to dependencies is created.
# For all of these dependencies, Nixpkgs' python3Packages are searched for appropriate names.
# Then, a Nix attribute set mapping component name to dependencies is created.
from urllib.request import urlopen
import subprocess
import os
import sys
import json
import re
from pkg_resources import Requirement, RequirementParseError
PREFIX = '# homeassistant.components.'
PKG_SET = 'python3Packages'
def get_version():
with open(os.path.dirname(sys.argv[0]) + '/default.nix') as f:
m = re.search('hassVersion = "([\\d\\.]+)";', f.read())
return m.group(1)
def fetch_reqs(version='master'):
requirements = {}
with urlopen('https://github.com/home-assistant/home-assistant/raw/{}/requirements_all.txt'.format(version)) as response:
components = []
for line in response.read().decode().splitlines():
if line == '':
components = []
elif line[:len(PREFIX)] == PREFIX:
component = line[len(PREFIX):]
components.append(component)
if component not in requirements:
requirements[component] = []
elif line[0] != '#':
for component in components:
requirements[component].append(line)
return requirements
# Store a JSON dump of Nixpkgs' python3Packages
output = subprocess.check_output(['nix-env', '-f', os.path.dirname(sys.argv[0]) + '/../../..', '-qa', '-A', PKG_SET, '--json'])
packages = json.loads(output)
def name_to_attr_path(req):
attr_paths = []
pattern = re.compile('python3\\.6-{}-\\d'.format(req), re.I)
for attr_path, package in packages.items():
if pattern.match(package['name']):
attr_paths.append(attr_path)
# Let's hope there's only one derivation with a matching name
assert(len(attr_paths) <= 1)
if attr_paths:
return attr_paths[0]
else:
return None
version = get_version()
requirements = fetch_reqs(version=version)
build_inputs = {}
for component, reqs in requirements.items():
attr_paths = []
for req in reqs:
try:
name = Requirement.parse(req).project_name
attr_path = name_to_attr_path(name)
if attr_path is not None:
# Add attribute path without "python3Packages." prefix
attr_paths.append(attr_path[len(PKG_SET + '.'):])
except RequirementParseError:
continue
else:
build_inputs[component] = attr_paths
# Only select components which have any dependency
#build_inputs = {k: v for k, v in build_inputs.items() if len(v) > 0}
with open(os.path.dirname(sys.argv[0]) + '/component-packages.nix', 'w') as f:
f.write('# Generated from parse-requirements.py\n')
f.write('# Do not edit!\n\n')
f.write('{\n')
f.write(' version = "{}";\n'.format(version))
f.write(' components = {\n')
for component, attr_paths in build_inputs.items():
f.write(' "{}" = ps: with ps; [ '.format(component))
f.write(' '.join(attr_paths))
f.write(' ];\n')
f.write(' };\n')
f.write('}\n')
Loading…
Cancel
Save