summary refs log blame commit diff
path: root/pkgs/servers/home-assistant/default.nix
blob: a03f3f6189e452cd8da2259022ed5c33139a7cd2 (plain) (tree)
1
2
3
4
5
6
7
8
9


                 
         
           
            

                                                                        
                       

                                                     
                        
 


                                                                           
                                    
 
                                                  


                   
                      

                                                                                                        
                                                                        
                   






                                                                          
          

         
 



                                                                      
                           


                                
                              
                                                                          




                                                                         
                                             



                                                              
                          






                                                                          
 




                                                                         

























                                                                          


















                                                                            



                                                             
















                                                                          












                                                                          

                                                                                      












                                                                          
                                                            
                   
                                                                    






                                                                      
                                     
                                 

          
      
 
                         

                                                                                                                     

    





                                                                                   
                                                                                                  
 


                                                     
                                                            
                           
 

                                             
                                                                           
 
                                                       
                               
 


                                                                     


                                            
                  
                  
                                                                    

    
                                                                                           
             
    
 

                                

                                                           
                                          
                                                      
                                          
                                                     
                                                                              

     
                           
                                        



                 
                  



                











                        

                                          
                                                
 

                                                                  


                                           
                 
                                                                 
                  
               
                        


                   
              
         

                                        
                                                                               
 


                                                                             
                    
           
                 


                   
           

                 
           








                         
               
               
                  
         

              
          
               

             
          

            
          
                

           
          
                  
                     

                   
               
            
           

                          
                         
          
               

               
             
            
                


              
            
          
                 
               

             
                
                     
                  
                  
                  

                  
              
                  
                
                 
             
           


             
            

                    
              



                              
                         
            
          
                
             
               
              
          

                       
            

           
            
            
                  
            
            
              
                  
                   
                   
             
                   
           
             

                
                




                
            
          


              
                     
             
                    


                


                    
            
            
             
             
           

                          
              
                       
                    
           



                        
                    
              

                      
          
             
              
               








                        
          
           
                    
              
              
              

             
             
          
                      
                     
             
                   
          
              
                  
                       
                   
             
                        
               
                       
               
           
          
                
         
                
                
                    
              
            
               
            
           
                    

                      
                        
              

                    

                  


                 

                   
         
          
         
           
                          
            
           
                     
                    
          
              
         
          
               
              

            
           
                 

                
              
          
             
                
            
                
              
               
                   

             

                 
           
                  
                  
            
         
                 
                   
           



                             
          
             
                      
           
                
            
                    
          
               




                      
             
              


               
         


                  
           
           
            
            
                                 
          
            
         
           
               
                
                

                    
             
                         
                  


                    
                
               



                             
            
                


             
            

           
              

               


                
                
                         
                   


                 
            
                     
              

            

                  
            

           
                           
                  
          
            
          
                       
                      
               
               
           
                 
            
            
            
           


             
                   
            
                   

                
                
               
           
             
         
             
                 
              
          
          
           
               

           
           


                     
            
             
         
                
          


                
            
         
            
         
                 
            
                  

                   
          
         

             

                 
              

                                                                              
               
            
          
               
           
         


            
           

                  
         







                  



               


                           
            
            
             
          
              
             
            




                 
             

                      
             
             
             
                   
          

             


                

                  
          

                  
                 
            
                      
               
              
              
             
         
            
          
           
              

                                                                                                 


                      



                                             


                                                                       

                                            

                                                                                                               

                                                                                           

                                                                       















                                                                                                   

                                                                                                          

                                                                                                                    


                                                                                                                                                   

                                 
                                                           

                                                                       






                                                                              
                   
                                   
                                


                                                         


                                                                          


                                                        

                                                                                                

                                                  

                                                           


                                                                                          

                                                                  


               

                          

                                                    
 


                                                           






                                                                                                

     
              
                                
                


                                          

    
                    
                                            
                                                                                          
                             
                                               
                                

    
{ stdenv
, lib
, fetchFromGitHub
, python3
, inetutils
, nixosTests

# Look up dependencies of specified components in component-packages.nix
, extraComponents ? [ ]

# Additional packages to add to propagatedBuildInputs
, extraPackages ? ps: []

# Override Python packages using
# self: super: { pkg = super.pkg.overridePythonAttrs (oldAttrs: { ... }); }
# Applied after defaultOverrides
, packageOverrides ? self: super: {}

# Skip pip install of required packages on startup
, skipPip ? true }:

let
  defaultOverrides = [
    # Override the version of some packages pinned in Home Assistant's setup.py and requirements_all.txt

    # Pinned due to API changes in aiopvpc>=2.2.0, remove after 2021.7.0
    (self: super: {
      aiopvpc = super.aiopvpc.overridePythonAttrs (oldAttr: rec {
        version = "2.1.2";
        src = fetchFromGitHub {
          owner = "azogue";
          repo = "aiopvpc";
          rev = "v${version}";
          sha256 = "0s8ki46dh39kw6qvsjcfcxa0gblyi33m3hry137kbi4lw5ws6qhr";
        };
      });
    })

    # 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 pyjwt>=2.0
    (self: super: {
      pyjwt = super.pyjwt.overridePythonAttrs (oldAttrs: rec {
        version = "1.7.1";
        src = oldAttrs.src.override {
          inherit version;
          sha256 = "15hflax5qkw1v6nssk1r0wkj83jgghskcmn875m3wgvpzdvajncd";
        };
        disabledTests = [
          "test_ec_verify_should_return_false_if_signature_invalid"
        ];
      });
    })

    # Pinned due to bug in ring-doorbell 0.7.0
    # https://github.com/tchellomello/python-ring-doorbell/issues/240
    (mkOverride "ring-doorbell" "0.6.2"
      "fbd537722a27b3b854c26506d894b7399bb8dc57ff36083285971227a2d46560")

    # Pinned due to API changes in pyatmo>=5.1.0
    (self: super: {
      pyatmo = super.pyatmo.overridePythonAttrs (oldAttrs: rec {
        version = "5.0.1";
        src = fetchFromGitHub {
          owner = "jabesq";
          repo = "pyatmo";
          rev = "v${version}";
          sha256 = "0can9v602iqfn0l01fd7gr63qzvcngfm0qka4s1x0pldh6avxmfh";
        };
      });
    })

    # Pinned due to API changes in pyatv>=0.8.0
    (self: super: {
      pyatv = super.pyatv.overridePythonAttrs (olAttrs: rec {
        version = "0.7.7";
        src = fetchFromGitHub {
          owner = "postlund";
          repo = "pyatv";
          rev = "v${version}";
          sha256 = "sha256-dPnh8XZN7ZVR2rYNnj7GSYXW5I2GNQwD/KRDTgs2AtI=";
        };
      });
    })

    # Pinned due to API changes in pyflunearyou>=2.0
    (self: super: {
      pyflunearyou = super.pyflunearyou.overridePythonAttrs (oldAttrs: rec {
        version = "1.0.7";
        src = fetchFromGitHub {
          owner = "bachya";
          repo = "pyflunearyou";
          rev = version;
          sha256 = "0hq55k298m9a90qb3lasw9bi093hzndrah00rfq94bp53aq0is99";
        };
        postPatch = ''
          substituteInPlace pyproject.toml \
            --replace "poetry.masonry.api" "poetry.core.masonry.api" \
            --replace 'msgpack = "^0.6.2"' 'msgpack = "*"' \
            --replace 'ujson = "^1.35"' 'ujson = "*"'
        '';
      });
    })

    # Pinned due to API changes in pylast 4.2.1
    (mkOverride "pylast" "4.2.0"
      "0zd0dn2l738ndz62vpa751z0ldnm91dcz9zzbvxv53r08l0s9yf3")

    # Pinned due to API changes in pyopenuv>=1.1.0
    (self: super: {
      pyopenuv = super.pyopenuv.overridePythonAttrs (oldAttrs: rec {
        version = "1.0.13";
        src = fetchFromGitHub {
          owner = "bachya";
          repo = "pyopenuv";
          rev = version;
          sha256 = "1gx9xjkyvqqy8410lnbshq1j5y4cb0cdc4m505g17rwdzdwb01y8";
        };
        postPatch = ''
          substituteInPlace pyproject.toml \
            --replace "poetry.masonry.api" "poetry.core.masonry.api"
        '';
      });
    })

    # Pinned due to API changes in pyruckus>0.12
    (self: super: {
      pyruckus = super.pyruckus.overridePythonAttrs (oldAttrs: rec {
        version = "0.12";
        src = fetchFromGitHub {
          owner = "gabe565";
          repo = "pyruckus";
          rev = version;
          sha256 = "0ykv6r6blbj3fg9fplk9i7xclkv5d93rwvx0fm5s8ms9f2s9ih8z";
        };
      });
    })

    (mkOverride "pysma" "0.4.3" "sha256-vriMnJFS7yfTyDT1f4sx1xEBTQjqc4ZHmkdHp1vcd+Q=")

    # Pinned due to API changes in eebrightbox>=0.0.5
    (self: super: {
      eebrightbox = super.eebrightbox.overridePythonAttrs (oldAttrs: rec {
        version = "0.0.4";
        src = fetchFromGitHub {
          owner = "krygal";
          repo = "eebrightbox";
          rev = version;
          sha256 = "0d8mmpwgrd7gymw5263r1v2wjv6dx6w6pq13d62fkfm4h2hya4a4";
        };
      });
    })

    # home-assistant-frontend does not exist in python3.pkgs
    (self: super: {
      home-assistant-frontend = self.callPackage ./frontend.nix { };
    })
  ];

  mkOverride = attrname: version: sha256:
    self: super: {
      ${attrname} = super.${attrname}.overridePythonAttrs (oldAttrs: {
        inherit version;
        src = oldAttrs.src.override {
          inherit version sha256;
        };
      });
    };

  py = python3.override {
    # Put packageOverrides at the start so they are applied after defaultOverrides
    packageOverrides = lib.foldr lib.composeExtensions (self: super: { }) ([ packageOverrides ] ++ defaultOverrides);
  };

  componentPackages = import ./component-packages.nix;

  availableComponents = builtins.attrNames componentPackages.components;

  getPackages = component: builtins.getAttr component componentPackages.components;

  componentBuildInputs = lib.concatMap (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 = "2021.6.6";

in with py.pkgs; buildPythonApplication rec {
  pname = "homeassistant";
  version = assert (componentPackages.version == hassVersion); hassVersion;

  # check REQUIRED_PYTHON_VER in homeassistant/const.py
  disabled = pythonOlder "3.8";

  # don't try and fail to strip 6600+ python files, it takes minutes!
  dontStrip = true;

  # PyPI tarball is missing tests/ directory
  src = fetchFromGitHub {
    owner = "home-assistant";
    repo = "core";
    rev = version;
    sha256 = "0r8l2qya9pdl65kq3xrnb1vhmbnxm3bj12hn1wyxmw56l8m9l5d5";
  };

  # leave this in, so users don't have to constantly update their downstream patch handling
  patches = [
  ];

  postPatch = ''
    substituteInPlace setup.py \
      --replace "attrs==21.2.0" "attrs" \
      --replace "awesomeversion==21.4.0" "awesomeversion" \
      --replace "bcrypt==3.1.7" "bcrypt" \
      --replace "cryptography==3.3.2" "cryptography" \
      --replace "pip>=8.0.3,<20.3" "pip" \
      --replace "ruamel.yaml==0.15.100" "ruamel.yaml"
    substituteInPlace tests/test_config.py --replace '"/usr"' '"/build/media"'
  '';

  propagatedBuildInputs = [
    # Only packages required in setup.py
    aiohttp
    astral
    async-timeout
    attrs
    awesomeversion
    bcrypt
    certifi
    ciso8601
    cryptography
    httpx
    jinja2
    pip
    pyjwt
    python-slugify
    pytz
    pyyaml
    requests
    ruamel_yaml
    voluptuous
    voluptuous-serialize
    yarl
  ] ++ lib.optionals (pythonOlder "3.9") [
    backports-zoneinfo
  ] ++ componentBuildInputs ++ extraBuildInputs;

  makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip";

  # upstream only tests on Linux, so do we.
  doCheck = stdenv.isLinux;

  checkInputs = [
    # test infrastructure (selectively from requirement_test.txt)
    pytest-aiohttp
    pytest-mock
    pytest-rerunfailures
    pytest-xdist
    pytestCheckHook
    requests-mock
    jsonpickle
    respx
    # 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"
    "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"
    "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"
    "dyson"
    "eafm"
    "ecobee"
    "econet"
    "ee_brightbox"
    "efergy"
    "elgato"
    "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"
    "flick_electric"
    "flo"
    "flume"
    "flunearyou"
    "flux"
    "folder"
    "folder_watcher"
    "foobot"
    "foscam"
    "freebox"
    "freedns"
    "fritz"
    "fritzbox"
    "fritzbox_callmonitor"
    "frontend"
    "garages_amsterdam"
    "garmin_connect"
    "gdacs"
    "generic"
    "generic_thermostat"
    "geo_json_events"
    "geo_location"
    "geo_rss_events"
    "geofency"
    "geonetnz_quakes"
    "geonetnz_volcano"
    "gios"
    "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"
    "homekit"
    "homekit_controller"
    "homematic"
    "homematicip_cloud"
    "honeywell"
    "html5"
    "http"
    "huawei_lte"
    "hue"
    "huisbaasje"
    "humidifier"
    "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"
    "keenetic_ndms2"
    "kira"
    "kmtronic"
    "knx"
    "kodi"
    "konnected"
    "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"
    "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"
    "motioneye"
    "mqtt"
    "mqtt_eventstream"
    "mqtt_json"
    "mqtt_room"
    "mqtt_statestream"
    "mullvad"
    "mutesync"
    "my"
    "myq"
    "mysensors"
    "nam"
    "namecheapdns"
    "neato"
    "netatmo"
    "nexia"
    "no_ip"
    "notify"
    "notion"
    "nsw_rural_fire_service_feed"
    "nuki"
    "number"
    "nws"
    "nx584"
    "omnilogic"
    "onboarding"
    "ondilo_ico"
    "openalpr_cloud"
    "openalpr_local"
    "openerz"
    "openhardwaremonitor"
    "opentherm_gw"
    "openuv"
    "openweathermap"
    "opnsense"
    "ovo_energy"
    "owntracks"
    "ozw"
    "panel_custom"
    "panel_iframe"
    "persistent_notification"
    "person"
    "philips_js"
    "pi_hole"
    "picnic"
    "ping"
    "plaato"
    "plant"
    "plex"
    "plugwise"
    "poolsense"
    "profiler"
    "prometheus"
    "proximity"
    "push"
    "pushbullet"
    "pvpc_hourly_pricing"
    "python_script"
    "rachio"
    "radarr"
    "rainmachine"
    "random"
    "recollect_waste"
    "recorder"
    "reddit"
    "remote"
    "rest"
    "rest_command"
    "rflink"
    "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"
    "sigfox"
    "sighthound"
    "simplisafe"
    "simulated"
    "slack"
    "sleepiq"
    "sma"
    "smappee"
    "smartthings"
    "smarttub"
    "smhi"
    "smtp"
    "snips"
    "solaredge"
    "soma"
    "somfy"
    "sonos"
    "soundtouch"
    "spaceapi"
    "speedtestdotnet"
    "spider"
    "spotify"
    "sql"
    "squeezebox"
    "ssdp"
    "startca"
    "statistics"
    "statsd"
    "stream"
    "stt"
    "subaru"
    "sun"
    "surepetcare"
    "switch"
    "switcher_kis"
    "system_health"
    "system_log"
    "tado"
    "tag"
    "tasmota"
    "tcp"
    "telegram"
    "tellduslive"
    "template"
    # disable tesla comonent tests while typer is incompatible with click>=8.0
    # "tesla"
    "threshold"
    "tibber"
    "tile"
    "time_date"
    "timer"
    "tod"
    "tomato"
    "toon"
    "tplink"
    "trace"
    "transmission"
    "trend"
    "tts"
    "tuya"
    "twentemilieu"
    "twilio"
    "twinkly"
    "twitch"
    "uk_transport"
    "unifi"
    "unifi_direct"
    "universal"
    "updater"
    "upnp"
    "uptime"
    "usgs_earthquakes_feed"
    "utility_meter"
    "uvc"
    "vacuum"
    "velbus"
    "venstar"
    "vera"
    "verisure"
    "version"
    "vesync"
    "vizio"
    "voicerss"
    "volumio"
    "vultr"
    "wake_on_lan"
    "wallbox"
    "water_heater"
    "waze_travel_time"
    "weather"
    "webhook"
    "webostv"
    "websocket_api"
    "wemo"
    "wiffi"
    "wilight"
    "wled"
    "workday"
    "worldclock"
    "wsdot"
    "wunderground"
    "xbox"
    "xiaomi"
    "xiaomi_aqara"
    "xiaomi_miio"
    "yamaha"
    "yandex_transport"
    "yandextts"
    "yeelight"
    "zeroconf"
    "zerproc"
    "zha"
    "zodiac"
    "zone"
    "zwave"
    "zwave_js"
  ] ++ lib.optionals (builtins.any (s: s == stdenv.hostPlatform.system) debugpy.meta.platforms) [
    "debugpy"
  ];

  pytestFlagsArray = [
    # parallelize test run
    "--numprocesses auto"
    # assign tests grouped by file to workers
    "--dist loadfile"
    # retry racy tests that end in "RuntimeError: Event loop is closed"
    "--reruns 3"
    "--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"
    # 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"
  ];

  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"
  ];

  preCheck = ''
    export HOME="$TEMPDIR"

    # 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
  '';

  passthru = {
    inherit availableComponents;
    python = py;
    tests = {
      inherit (nixosTests) home-assistant;
    };
  };

  meta = with lib; {
    homepage = "https://home-assistant.io/";
    description = "Open source home automation that puts local control and privacy first";
    license = licenses.asl20;
    maintainers = teams.home-assistant.members;
    platforms = platforms.linux;
  };
}