nixpkgs/pkgs/servers/home-assistant/default.nix
Guillaume Girol 33afbf39f6 treewide: switch to nativeCheckInputs
checkInputs used to be added to nativeBuildInputs. Now we have
nativeCheckInputs to do that instead. Doing this treewide change allows
to keep hashes identical to before the introduction of
nativeCheckInputs.
2023-01-21 12:00:00 +00:00

517 lines
15 KiB
Nix

{ stdenv
, lib
, callPackage
, fetchFromGitHub
, fetchpatch
, python3
, substituteAll
, ffmpeg-headless
, inetutils
, nixosTests
, home-assistant
, testers
# Look up dependencies of specified components in component-packages.nix
, extraComponents ? [ ]
# 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
, 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
(self: super: {
advantage-air = super.advantage-air.overridePythonAttrs (oldAttrs: rec {
version = "0.4.1";
src = super.fetchPypi {
pname = "advantage_air";
inherit version;
hash = "sha256-I9HMDLZX9xKDJuYSAweM2r4v3ZKevHTn5dHTYxN3EuE=";
};
});
# https://github.com/postlund/pyatv/issues/1879
aiohttp = super.aiohttp.overridePythonAttrs (oldAttrs: rec {
pname = "aiohttp";
version = "3.8.1";
src = self.fetchPypi {
inherit pname version;
hash = "sha256-/FRx4aVN4V73HBvG6+gNTcaB6mAOaL/Ry85AQn8LdXg=";
};
});
aiowatttime = super.aiowatttime.overridePythonAttrs (oldAttrs: rec {
version = "0.1.1";
src = fetchFromGitHub {
owner = "bachya";
repo = "aiowatttime";
rev = "refs/tags/${version}";
hash = "sha256-tWnxGLJT+CRFvkhxFamHxnLXBvoR8tfOvzH1o1i5JJg=";
};
});
astral = super.astral.overridePythonAttrs (oldAttrs: rec {
pname = "astral";
version = "2.2";
src = self.fetchPypi {
inherit pname version;
hash = "sha256-5B2ZZ9XEi+QhNGVS8PTe2tQ/85qDV09f8q0ytmJ7b74=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace "poetry.masonry" "poetry.core.masonry"
'';
propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [
self.pytz
];
});
caldav = super.caldav.overridePythonAttrs (old: rec {
version = "0.9.1";
src = fetchFromGitHub {
owner = "python-caldav";
repo = "caldav";
rev = "v${version}";
hash = "sha256-Gil0v4pGyp5+TnYPjb8Vk0xTqnQKaeD8Ko/ZWhvkbUk=";
};
postPatch = ''
substituteInPlace setup.py \
--replace ", 'xandikos<0.2.4'" "" \
--replace ", 'radicale'" ""
'';
nativeCheckInputs = old.nativeCheckInputs ++ [ self.nose ];
});
dsmr-parser = super.dsmr-parser.overridePythonAttrs (oldAttrs: rec {
version = "0.33";
src = fetchFromGitHub {
owner = "ndokter";
repo = "dsmr_parser";
rev = "refs/tags/v${version}";
hash = "sha256-Phx8Yqx6beTzkQv0fU8Pfs2btPgKVARdO+nMcne1S+w=";
};
});
gridnet = super.gridnet.overridePythonAttrs (oldAttrs: rec {
version = "4.0.0";
src = fetchFromGitHub {
owner = "klaasnicolaas";
repo = "python-gridnet";
rev = "refs/tags/v${version}";
hash = "sha256-Ihs8qUx50tAUcRBsVArRhzoLcQUi1vbYh8sPyK75AEk=";
};
});
icalendar = super.icalendar.overridePythonAttrs (oldAttrs: rec {
version = "4.1.0";
src = self.fetchPypi {
inherit (oldAttrs) pname;
inherit version;
hash = "sha256-l0i3wC78xD5Y0GFa4JdqxPJl6Q2t7ptPiE3imQXBs5U=";
};
});
# Pinned due to API changes in 10.0
mcstatus = super.mcstatus.overridePythonAttrs (oldAttrs: rec {
version = "9.3.0";
src = fetchFromGitHub {
owner = "py-mine";
repo = "mcstatus";
rev = "refs/tags/v${version}";
hash = "sha256-kNThVElEDqhbCitktBv5tQkjMaU4IsX0dJk63hvLhb0=";
};
});
# Pinned due to API changes in 1.3.0
ovoenergy = super.ovoenergy.overridePythonAttrs (oldAttrs: rec {
version = "1.2.0";
src = fetchFromGitHub {
owner = "timmo001";
repo = "ovoenergy";
rev = "refs/tags/v${version}";
hash = "sha256-OSK74uvpHuEtWgbLVFrz1NO7lvtHbt690smGQ+GlsOI=";
};
});
# Pinned due to API changes in 0.1.0
poolsense = super.poolsense.overridePythonAttrs (oldAttrs: rec {
version = "0.0.8";
src = super.fetchPypi {
pname = "poolsense";
inherit version;
hash = "sha256-17MHrYRmqkH+1QLtgq2d6zaRtqvb9ju9dvPt9gB2xCc=";
};
});
# Pinned due to API changes >0.3.5.3
pyatag = super.pyatag.overridePythonAttrs (oldAttrs: rec {
version = "0.3.5.3";
src = fetchFromGitHub {
owner = "MatsNl";
repo = "pyatag";
rev = version;
sha256 = "00ly4injmgrj34p0lyx7cz2crgnfcijmzc0540gf7hpwha0marf6";
};
});
# https://github.com/home-assistant/core/pull/80931
pyjwt = super.pyjwt.overridePythonAttrs (oldAttrs: rec {
version = "2.5.0";
src = super.fetchPypi {
pname = "PyJWT";
inherit version;
hash = "sha256-53q4lICQXYaZhEKsV4jzUzP6hfZQR6U0rcOO3zyI/Ds=";
};
});
pymodbus = super.pymodbus.overridePythonAttrs (oldAttrs: rec {
version = "2.5.3";
src = fetchFromGitHub {
owner = "riptideio";
repo = "pymodbus";
rev= "refs/tags/v${version}";
hash = "sha256-pf1TU/imBqNVYdG4XX8fnma8O8kQHuOHu6DT3E/PUk4=";
};
});
# Pinned due to API changes in 1.0.24
pysensibo = super.pysensibo.overridePythonAttrs (oldAttrs: rec {
version = "1.0.22";
src = fetchFromGitHub {
owner = "andrey-git";
repo = "pysensibo";
rev = "refs/tags/${version}";
hash = "sha256-AUcdKcdoYCg8OgUcFoLLpNK5GQMTg89XCR5CkTfNkcc=";
};
});
python-slugify = super.python-slugify.overridePythonAttrs (oldAttrs: rec {
pname = "python-slugify";
version = "4.0.1";
src = super.fetchPypi {
inherit pname version;
hash = "sha256-aaUXdm4AwSaOW7/A0BCgqFCN4LGNMK1aH/NX+K5yQnA=";
};
});
python-telegram-bot = super.python-telegram-bot.overridePythonAttrs (oldAttrs: rec {
version = "13.15";
src = fetchFromGitHub {
owner = "python-telegram-bot";
repo = "python-telegram-bot";
rev = "v${version}";
hash = "sha256-EViSjr/nnuJIDTwV8j/O50hJkWV3M5aTNnWyzrinoyg=";
};
propagatedBuildInputs = [
self.APScheduler
self.cachetools
self.certifi
self.cryptography
self.decorator
self.future
self.tornado
self.urllib3
];
setupPyGlobalFlags = [ "--with-upstream-urllib3" ];
postPatch = ''
rm -r telegram/vendor
substituteInPlace requirements.txt \
--replace "APScheduler==3.6.3" "APScheduler" \
--replace "cachetools==4.2.2" "cachetools" \
--replace "tornado==6.1" "tornado"
'';
doCheck = false;
});
pytradfri = super.pytradfri.overridePythonAttrs (oldAttrs: rec {
version = "9.0.0";
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "pytradfri";
rev = "refs/tags/${version}";
hash = "sha256-12ol+2CnoPfkxmDGJJAkoafHGpQuWC4lh0N7lSvx2DE=";
};
});
pysoma = super.pysoma.overridePythonAttrs (oldAttrs: rec {
version = "0.0.10";
src = super.fetchPypi {
pname = "pysoma";
inherit version;
hash = "sha256-sU1qHbAjdIUu0etjate8+U1zvunbw3ddBtDVUU10CuE=";
};
});
# Pinned due to API changes in 0.3.0
tailscale = super.tailscale.overridePythonAttrs (oldAttrs: rec {
version = "0.2.0";
src = fetchFromGitHub {
owner = "frenck";
repo = "python-tailscale";
rev = "refs/tags/v${version}";
hash = "sha256-/tS9ZMUWsj42n3MYPZJYJELzX3h02AIHeRZmD2SuwWE=";
};
});
# Pinned due to API changes in 0.4.0
vilfo-api-client = super.vilfo-api-client.overridePythonAttrs (oldAttrs: rec {
version = "0.3.3";
src = fetchFromGitHub {
owner = "ManneW";
repo = "vilfo-api-client-python";
rev = "v${version}";
sha256 = "1gy5gpsg99rcm1cc3m30232za00r9i46sp74zpd12p3vzz1wyyqf";
};
});
# Pinned due to API changes in 2.0
vsure = super.vsure.overridePythonAttrs (oldAttrs: rec {
version = "1.8.1";
src = super.fetchPypi {
pname = "vsure";
inherit version;
hash = "sha256-Zh83t7yjZU2NjOgCkqPUHbqvEyEWXGITRgr5d2fLtRI=";
};
});
# Pinned due to API changes ~1.0
vultr = super.vultr.overridePythonAttrs (oldAttrs: rec {
version = "0.1.2";
src = fetchFromGitHub {
owner = "spry-group";
repo = "python-vultr";
rev = "v${version}";
sha256 = "1qjvvr2v9gfnwskdl0ayazpcmiyw9zlgnijnhgq9mcri5gq9jw5h";
};
});
# home-assistant-frontend does not exist in python3.pkgs
home-assistant-frontend = self.callPackage ./frontend.nix { };
})
];
python = 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;
inherit (componentPackages) supportedComponentsWithTests;
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 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 = "2023.1.5";
in python.pkgs.buildPythonApplication rec {
pname = "homeassistant";
version = assert (componentPackages.version == hassVersion); hassVersion;
format = "pyproject";
# check REQUIRED_PYTHON_VER in homeassistant/const.py
disabled = python.pythonOlder "3.9";
# 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 = "refs/tags/${version}";
hash = "sha256-gqWkj90Vw+Pne0Iseet1Jz0Eh3YpUiqspGltvU5Pxro=";
};
# leave this in, so users don't have to constantly update their downstream patch handling
patches = [
(substituteAll {
src = ./patches/ffmpeg-path.patch;
ffmpeg = "${lib.getBin ffmpeg-headless}/bin/ffmpeg";
})
];
postPatch = let
relaxedConstraints = [
"aiohttp"
"attrs"
"awesomeversion"
"bcrypt"
"ciso8601"
"cryptography"
"home-assistant-bluetooth"
"httpx"
"ifaddr"
"orjson"
"PyJWT"
"requests"
"typing-extensions"
"yarl"
];
in ''
sed -r -i \
${lib.concatStringsSep "\n" (map (package:
''-e 's/${package}[<>=]+.*/${package}",/g' \''
) relaxedConstraints)}
pyproject.toml
substituteInPlace tests/test_config.py --replace '"/usr"' '"/build/media"'
'';
propagatedBuildInputs = with python.pkgs; [
# Only packages required in setup.py
aiohttp
astral
async-timeout
atomicwrites-homeassistant
attrs
awesomeversion
bcrypt
certifi
ciso8601
cryptography
httpx
home-assistant-bluetooth
ifaddr
jinja2
lru-dict
orjson
pip
pyjwt
python-slugify
pyyaml
requests
voluptuous
voluptuous-serialize
yarl
# Not in setup.py, but used in homeassistant/util/package.py
setuptools
# Not in setup.py, but uncounditionally imported via tests/conftest.py
paho-mqtt
] ++ componentBuildInputs ++ extraBuildInputs;
makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip";
# upstream only tests on Linux, so do we.
doCheck = stdenv.isLinux;
nativeCheckInputs = with python.pkgs; [
# test infrastructure (selectively from requirement_test.txt)
freezegun
pytest-asyncio
pytest-aiohttp
pytest-freezegun
pytest-mock
pytest-rerunfailures
pytest-socket
pytest-unordered
pytest-xdist
pytestCheckHook
requests-mock
respx
stdlib-list
# required by tests/auth/mfa_modules
pyotp
] ++ lib.concatMap (component: getPackages component python.pkgs) [
# some components are needed even if tests in tests/components are disabled
"default_config"
"hue"
];
pytestFlagsArray = [
# 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"
# 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"
];
disabledTestPaths = [
# we neither run nor distribute hassfest
"tests/hassfest"
# we don't care about code quality
"tests/pylint"
# 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_merge"
# Tests are flaky
"test_config_platform_valid"
# Test requires pylint>=2.13.0
"test_invalid_discovery_info"
];
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
'';
postInstall = ''
cp -v ${extraComponentsFile} $out/extra_components
cp -v ${extraPackagesFile} $out/extra_packages
'';
passthru = {
inherit
availableComponents
extraComponents
getPackages
python
supportedComponentsWithTests;
tests = {
nixos = nixosTests.home-assistant;
components = callPackage ./tests.nix { };
version = testers.testVersion {
package = home-assistant;
command = "hass --version";
};
};
};
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;
};
}