Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at devShellTools-shell 599 lines 18 kB view raw
1{ 2 stdenv, 3 lib, 4 callPackage, 5 fetchFromGitHub, 6 fetchPypi, 7 python313, 8 replaceVars, 9 ffmpeg-headless, 10 inetutils, 11 nixosTests, 12 home-assistant, 13 testers, 14 15 # Look up dependencies of specified components in component-packages.nix 16 extraComponents ? [ ], 17 18 # Additional packages to add to propagatedBuildInputs 19 extraPackages ? ps: [ ], 20 21 # Override Python packages using 22 # self: super: { pkg = super.pkg.overridePythonAttrs (oldAttrs: { ... }); } 23 # Applied after defaultOverrides 24 packageOverrides ? self: super: { }, 25 26 # Skip pip install of required packages on startup 27 skipPip ? true, 28}: 29 30let 31 defaultOverrides = [ 32 # Override the version of some packages pinned in Home Assistant's setup.py and requirements_all.txt 33 34 (self: super: { 35 aioelectricitymaps = super.aioelectricitymaps.overridePythonAttrs (oldAttrs: rec { 36 version = "0.4.0"; 37 src = fetchFromGitHub { 38 owner = "jpbede"; 39 repo = "aioelectricitymaps"; 40 rev = "refs/tags/v${version}"; 41 hash = "sha256-q06B40c0uvSuzH/3YCoxg4p9aNIOPrphsoESktF+B14="; 42 }; 43 nativeCheckInputs = with self; [ 44 aresponses 45 ]; 46 }); 47 48 aioskybell = super.aioskybell.overridePythonAttrs (oldAttrs: rec { 49 version = "22.7.0"; 50 src = fetchFromGitHub { 51 owner = "tkdrob"; 52 repo = "aioskybell"; 53 rev = "refs/tags/${version}"; 54 hash = "sha256-aBT1fDFtq1vasTvCnAXKV2vmZ6LBLZqRCiepv1HDJ+Q="; 55 }; 56 }); 57 58 aiowatttime = super.aiowatttime.overridePythonAttrs (oldAttrs: rec { 59 version = "0.1.1"; 60 src = fetchFromGitHub { 61 owner = "bachya"; 62 repo = "aiowatttime"; 63 rev = "refs/tags/${version}"; 64 hash = "sha256-tWnxGLJT+CRFvkhxFamHxnLXBvoR8tfOvzH1o1i5JJg="; 65 }; 66 postPatch = '' 67 substituteInPlace pyproject.toml --replace-fail \ 68 '"setuptools >= 35.0.2", "wheel >= 0.29.0", "poetry>=0.12"' \ 69 '"poetry-core"' 70 ''; 71 }); 72 73 astral = super.astral.overridePythonAttrs (oldAttrs: rec { 74 pname = "astral"; 75 version = "2.2"; 76 src = fetchPypi { 77 inherit pname version; 78 hash = "sha256-5B2ZZ9XEi+QhNGVS8PTe2tQ/85qDV09f8q0ytmJ7b74="; 79 }; 80 postPatch = '' 81 substituteInPlace pyproject.toml \ 82 --replace-fail "poetry>=1.0.0b1" "poetry-core" \ 83 --replace-fail "poetry.masonry" "poetry.core.masonry" 84 ''; 85 propagatedBuildInputs = (oldAttrs.propagatedBuildInputs or [ ]) ++ [ 86 self.pytz 87 ]; 88 }); 89 90 async-timeout = super.async-timeout.overridePythonAttrs (oldAttrs: rec { 91 version = "4.0.3"; 92 src = fetchFromGitHub { 93 owner = "aio-libs"; 94 repo = "async-timeout"; 95 tag = "v${version}"; 96 hash = "sha256-gJGVRm7YMWnVicz2juHKW8kjJBxn4/vQ/kc2kQyl1i4="; 97 }; 98 }); 99 100 av = super.av.overridePythonAttrs (rec { 101 version = "13.1.0"; 102 src = fetchFromGitHub { 103 owner = "PyAV-Org"; 104 repo = "PyAV"; 105 tag = "v${version}"; 106 hash = "sha256-x2a9SC4uRplC6p0cD7fZcepFpRidbr6JJEEOaGSWl60="; 107 }; 108 }); 109 110 brother = super.brother.overridePythonAttrs (rec { 111 version = "4.3.1"; 112 src = fetchFromGitHub { 113 owner = "bieniu"; 114 repo = "brother"; 115 tag = version; 116 hash = "sha256-fWa5FNBGV8tnJ3CozMicXLGsDvnTjNzU8PdV266MeeQ="; 117 }; 118 }); 119 120 google-genai = super.google-genai.overridePythonAttrs (old: rec { 121 version = "1.7.0"; 122 src = fetchFromGitHub { 123 owner = "googleapis"; 124 repo = "python-genai"; 125 tag = "v${version}"; 126 hash = "sha256-vmrFPE7H9s9varrP0s6WK4opoU1hREH7rVVjrKiXY5E="; 127 }; 128 }); 129 130 gspread = super.gspread.overridePythonAttrs (oldAttrs: rec { 131 version = "5.12.4"; 132 src = fetchFromGitHub { 133 owner = "burnash"; 134 repo = "gspread"; 135 rev = "refs/tags/v${version}"; 136 hash = "sha256-i+QbnF0Y/kUMvt91Wzb8wseO/1rZn9xzeA5BWg1haks="; 137 }; 138 dependencies = with self; [ 139 requests 140 ]; 141 }); 142 143 mcp = super.mcp.overridePythonAttrs (oldAttrs: rec { 144 version = "1.5.0"; 145 src = fetchFromGitHub { 146 inherit (oldAttrs.src) owner repo; 147 tag = "v${version}"; 148 hash = "sha256-Z2NN6k4mD6NixDON1MUOELpBZW9JvMvFErcCbFPdg2o="; 149 }; 150 }); 151 152 notifications-android-tv = super.notifications-android-tv.overridePythonAttrs (oldAttrs: rec { 153 version = "0.1.5"; 154 format = "setuptools"; 155 156 src = fetchFromGitHub { 157 owner = "engrbm87"; 158 repo = "notifications_android_tv"; 159 rev = "refs/tags/${version}"; 160 hash = "sha256-adkcUuPl0jdJjkBINCTW4Kmc16C/HzL+jaRZB/Qr09A="; 161 }; 162 163 nativeBuildInputs = with self; [ 164 setuptools 165 ]; 166 167 propagatedBuildInputs = with self; [ 168 requests 169 ]; 170 171 doCheck = false; # no tests 172 }); 173 174 openhomedevice = super.openhomedevice.overridePythonAttrs (oldAttrs: rec { 175 version = "2.2"; 176 src = fetchFromGitHub { 177 inherit (oldAttrs.src) owner repo; 178 rev = "refs/tags/${version}"; 179 hash = "sha256-GGp7nKFH01m1KW6yMkKlAdd26bDi8JDWva6OQ0CWMIw="; 180 }; 181 }); 182 183 plexapi = super.plexapi.overrideAttrs (oldAttrs: rec { 184 version = "4.15.16"; 185 src = fetchFromGitHub { 186 owner = "pkkid"; 187 repo = "python-plexapi"; 188 tag = version; 189 hash = "sha256-NwGGNN6LC3gvE8zoVL5meNWMbqZjJ+6PcU2ebJTfJmU="; 190 }; 191 }); 192 193 # Pinned due to API changes in 0.1.0 194 poolsense = super.poolsense.overridePythonAttrs (oldAttrs: rec { 195 version = "0.0.8"; 196 src = fetchPypi { 197 pname = "poolsense"; 198 inherit version; 199 hash = "sha256-17MHrYRmqkH+1QLtgq2d6zaRtqvb9ju9dvPt9gB2xCc="; 200 }; 201 }); 202 203 # Pinned due to API changes >0.3.5.3 204 pyatag = super.pyatag.overridePythonAttrs (oldAttrs: rec { 205 version = "0.3.5.3"; 206 src = fetchFromGitHub { 207 owner = "MatsNl"; 208 repo = "pyatag"; 209 rev = version; 210 sha256 = "00ly4injmgrj34p0lyx7cz2crgnfcijmzc0540gf7hpwha0marf6"; 211 }; 212 }); 213 214 pydexcom = super.pydexcom.overridePythonAttrs (oldAttrs: rec { 215 version = "0.2.3"; 216 src = fetchFromGitHub { 217 owner = "gagebenne"; 218 repo = "pydexcom"; 219 rev = "refs/tags/${version}"; 220 hash = "sha256-ItDGnUUUTwCz4ZJtFVlMYjjoBPn2h8QZgLzgnV2T/Qk="; 221 }; 222 }); 223 224 pyflume = super.pyflume.overridePythonAttrs (oldAttrs: rec { 225 version = "0.6.5"; 226 src = fetchFromGitHub { 227 owner = "ChrisMandich"; 228 repo = "PyFlume"; 229 rev = "refs/tags/v${version}"; 230 hash = "sha256-kIE3y/qlsO9Y1MjEQcX0pfaBeIzCCHk4f1Xa215BBHo="; 231 }; 232 dependencies = oldAttrs.propagatedBuildInputs or [ ] ++ [ 233 self.pytz 234 ]; 235 }); 236 237 pykaleidescape = super.pykaleidescape.overridePythonAttrs (oldAttrs: rec { 238 version = "1.0.1"; 239 src = fetchFromGitHub { 240 inherit (oldAttrs.src) owner repo; 241 rev = "refs/tags/v${version}"; 242 hash = "sha256-KM/gtpsQ27QZz2uI1t/yVN5no0zp9LZag1duAJzK55g="; 243 }; 244 }); 245 246 pyoctoprintapi = super.pyoctoprintapi.overridePythonAttrs (oldAttrs: rec { 247 version = "0.1.12"; 248 src = fetchFromGitHub { 249 owner = "rfleming71"; 250 repo = "pyoctoprintapi"; 251 rev = "refs/tags/v${version}"; 252 hash = "sha256-Jf/zYnBHVl3TYxFy9Chy6qNH/eCroZkmUOEWfd62RIo="; 253 }; 254 }); 255 256 # snmp component does not support pysnmp 7.0+ 257 pysnmp = super.pysnmp.overridePythonAttrs (oldAttrs: rec { 258 version = "6.2.6"; 259 src = fetchFromGitHub { 260 owner = "lextudio"; 261 repo = "pysnmp"; 262 tag = "v${version}"; 263 hash = "sha256-+FfXvsfn8XzliaGUKZlzqbozoo6vDxUkgC87JOoVasY="; 264 }; 265 }); 266 267 pysnmpcrypto = super.pysnmpcrypto.overridePythonAttrs (oldAttrs: rec { 268 version = "0.0.4"; 269 src = fetchFromGitHub { 270 owner = "lextudio"; 271 repo = "pysnmpcrypto"; 272 tag = "v${version}"; 273 hash = "sha256-f0w4Nucpe+5VE6nhlnePRH95AnGitXeT3BZb3dhBOTk="; 274 }; 275 build-system = with self; [ setuptools ]; 276 postPatch = '' 277 # ValueError: invalid literal for int() with base 10: 'post0' in File "<string>", line 104, in <listcomp> 278 substituteInPlace setup.py --replace \ 279 "observed_version = [int(x) for x in setuptools.__version__.split('.')]" \ 280 "observed_version = [36, 2, 0]" 281 ''; 282 }); 283 284 pysnooz = super.pysnooz.overridePythonAttrs (oldAttrs: rec { 285 version = "0.8.6"; 286 src = fetchFromGitHub { 287 owner = "AustinBrunkhorst"; 288 repo = "pysnooz"; 289 rev = "refs/tags/v${version}"; 290 hash = "sha256-hJwIObiuFEAVhgZXYB9VCeAlewBBnk0oMkP83MUCpyU="; 291 }; 292 }); 293 294 pytradfri = super.pytradfri.overridePythonAttrs (oldAttrs: rec { 295 version = "9.0.1"; 296 src = fetchFromGitHub { 297 owner = "home-assistant-libs"; 298 repo = "pytradfri"; 299 rev = "refs/tags/${version}"; 300 hash = "sha256-xOdTzG0bF5p1QpkXv2btwrVugQRjSwdAj8bXcC0IoQg="; 301 }; 302 patches = [ ]; 303 doCheck = false; 304 }); 305 306 # Pinned due to API changes ~1.0 307 vultr = super.vultr.overridePythonAttrs (oldAttrs: rec { 308 version = "0.1.2"; 309 src = fetchFromGitHub { 310 owner = "spry-group"; 311 repo = "python-vultr"; 312 rev = version; 313 hash = "sha256-sHCZ8Csxs5rwg1ZG++hP3MfK7ldeAdqm5ta9tEXeW+I="; 314 }; 315 }); 316 317 wolf-comm = super.wolf-comm.overridePythonAttrs (rec { 318 version = "0.0.23"; 319 src = fetchFromGitHub { 320 owner = "janrothkegel"; 321 repo = "wolf-comm"; 322 tag = version; 323 hash = "sha256-LpehooW3vmohiyMwOQTFNLiNCsaLKelWQxQk8bl+y1k="; 324 }; 325 }); 326 327 # internal python packages only consumed by home-assistant itself 328 hass-web-proxy-lib = self.callPackage ./python-modules/hass-web-proxy-lib { }; 329 home-assistant-frontend = self.callPackage ./frontend.nix { }; 330 home-assistant-intents = self.callPackage ./intents.nix { }; 331 homeassistant = self.toPythonModule home-assistant; 332 pytest-homeassistant-custom-component = 333 self.callPackage ./pytest-homeassistant-custom-component.nix 334 { }; 335 }) 336 ]; 337 338 python = python313.override { 339 self = python; 340 packageOverrides = lib.composeManyExtensions (defaultOverrides ++ [ packageOverrides ]); 341 }; 342 343 componentPackages = import ./component-packages.nix; 344 345 availableComponents = builtins.attrNames componentPackages.components; 346 347 inherit (componentPackages) supportedComponentsWithTests; 348 349 getPackages = component: componentPackages.components.${component}; 350 351 componentBuildInputs = lib.concatMap (component: getPackages component python.pkgs) extraComponents; 352 353 # Ensure that we are using a consistent package set 354 extraBuildInputs = extraPackages python.pkgs; 355 356 # Don't forget to run update-component-packages.py after updating 357 hassVersion = "2025.7.4"; 358 359in 360python.pkgs.buildPythonApplication rec { 361 pname = "homeassistant"; 362 version = 363 assert (componentPackages.version == hassVersion); 364 hassVersion; 365 pyproject = true; 366 367 # check REQUIRED_PYTHON_VER in homeassistant/const.py 368 disabled = python.pythonOlder "3.13"; 369 370 # don't try and fail to strip 6600+ python files, it takes minutes! 371 dontStrip = true; 372 373 # Primary source is the git, which has the tests and allows bisecting the core 374 src = fetchFromGitHub { 375 owner = "home-assistant"; 376 repo = "core"; 377 tag = version; 378 hash = "sha256-2seMh1trP3PYnuQmWadTAiAPaI+v45+uzn9xkgUuGNE="; 379 }; 380 381 # Secondary source is pypi sdist for translations 382 sdist = fetchPypi { 383 inherit pname version; 384 hash = "sha256-KwiwgQ8gAMlHLzpuYYdcLXabVrukhnfFlaODyFpuF88="; 385 }; 386 387 build-system = with python.pkgs; [ 388 setuptools 389 ]; 390 391 pythonRelaxDeps = true; 392 393 # extract translations from pypi sdist 394 prePatch = '' 395 tar --extract --gzip --file $sdist --strip-components 1 --wildcards "**/translations" 396 ''; 397 398 # leave this in, so users don't have to constantly update their downstream patch handling 399 patches = [ 400 # Follow symlinks in /var/lib/hass/www 401 ./patches/static-follow-symlinks.patch 402 403 # Copy default blueprints without preserving permissions 404 ./patches/default-blueprint-permissions.patch 405 406 # Patch path to ffmpeg binary 407 (replaceVars ./patches/ffmpeg-path.patch { 408 ffmpeg = "${lib.getExe ffmpeg-headless}"; 409 }) 410 ]; 411 412 postPatch = '' 413 substituteInPlace tests/test_core_config.py --replace-fail '"/usr"' "\"$NIX_BUILD_TOP/media\"" 414 415 substituteInPlace pyproject.toml \ 416 --replace-fail "setuptools==78.1.1" setuptools 417 ''; 418 419 dependencies = with python.pkgs; [ 420 # Only packages required in pyproject.toml 421 aiodns 422 aiofiles 423 aiohasupervisor 424 aiohttp 425 aiohttp-asyncmdnsresolver 426 aiohttp-cors 427 aiohttp-fast-zlib 428 aiozoneinfo 429 annotatedyaml 430 astral 431 async-interrupt 432 atomicwrites-homeassistant 433 attrs 434 audioop-lts 435 awesomeversion 436 bcrypt 437 certifi 438 ciso8601 439 cronsim 440 cryptography 441 fnv-hash-fast 442 ha-ffmpeg 443 hass-nabucasa 444 hassil 445 home-assistant-bluetooth 446 home-assistant-intents 447 httpx 448 ifaddr 449 jinja2 450 lru-dict 451 mutagen 452 numpy 453 orjson 454 packaging 455 pillow 456 propcache 457 psutil-home-assistant 458 pyjwt 459 pymicro-vad 460 pyopenssl 461 pyspeex-noise 462 python-slugify 463 pyturbojpeg 464 pyyaml 465 requests 466 securetar 467 sqlalchemy 468 standard-aifc 469 standard-telnetlib 470 typing-extensions 471 ulid-transform 472 urllib3 473 uv 474 voluptuous 475 voluptuous-openapi 476 voluptuous-serialize 477 webrtc-models 478 yarl 479 zeroconf 480 # REQUIREMENTS in homeassistant/auth/mfa_modules/totp.py and homeassistant/auth/mfa_modules/notify.py 481 pyotp 482 pyqrcode 483 ]; 484 485 makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip"; 486 487 # upstream only tests on Linux, so do we. 488 doCheck = stdenv.hostPlatform.isLinux; 489 490 nativeCheckInputs = 491 with python.pkgs; 492 [ 493 # test infrastructure (selectively from requirement_test.txt) 494 freezegun 495 pytest-asyncio 496 pytest-aiohttp 497 pytest-freezer 498 pytest-mock 499 pytest-socket 500 pytest-timeout 501 pytest-unordered 502 pytest-xdist 503 pytestCheckHook 504 requests-mock 505 respx 506 syrupy 507 tomli 508 # Sneakily imported in tests/conftest.py 509 paho-mqtt 510 # Used in tests/non_packaged_scripts/test_alexa_locales.py 511 beautifulsoup4 512 ] 513 ++ lib.concatMap (component: getPackages component python.pkgs) [ 514 # some components are needed even if tests in tests/components are disabled 515 "default_config" 516 "hue" 517 "qwikswitch" 518 ]; 519 520 pytestFlags = [ 521 # assign tests grouped by file to workers 522 "--dist=loadfile" 523 # enable full variable printing on error 524 "--showlocals" 525 ]; 526 527 enabledTestPaths = [ 528 # tests are located in tests/ 529 "tests" 530 ]; 531 532 disabledTestPaths = [ 533 # we neither run nor distribute hassfest 534 "tests/hassfest" 535 # we don't care about code quality 536 "tests/pylint" 537 # redundant component import test, which would make debugpy & sentry expensive to review 538 "tests/test_circular_imports.py" 539 # don't bulk test all components 540 "tests/components" 541 # AssertionError: assert 1 == 0 542 "tests/test_config.py::test_merge" 543 # checks whether pip is installed 544 "tests/util/test_package.py::test_check_package_fragment" 545 # flaky 546 "tests/test_bootstrap.py::test_setup_hass_takes_longer_than_log_slow_startup" 547 "tests/test_test_fixtures.py::test_evict_faked_translations" 548 "tests/helpers/test_backup.py::test_async_get_manager" 549 # (2025.7.0) Fails to find name of tracked time interval in scheduled jobs 550 "tests/helpers/test_event.py::test_track_time_interval_name" 551 # (2025.7.2) Exception string mismatch (non-blocking vs non blocking) 552 "tests/test_core.py::test_services_call_return_response_requires_blocking" 553 ]; 554 555 preCheck = '' 556 export HOME="$TEMPDIR" 557 558 # the tests require the existance of a media dir 559 mkdir "$NIX_BUILD_TOP"/media 560 561 # put ping binary into PATH, e.g. for wake_on_lan tests 562 export PATH=${inetutils}/bin:$PATH 563 ''; 564 565 passthru = { 566 inherit 567 availableComponents 568 extraComponents 569 getPackages 570 python 571 supportedComponentsWithTests 572 ; 573 pythonPath = python.pkgs.makePythonPath (componentBuildInputs ++ extraBuildInputs); 574 frontend = python.pkgs.home-assistant-frontend; 575 intents = python.pkgs.home-assistant-intents; 576 tests = { 577 nixos = nixosTests.home-assistant; 578 components = callPackage ./tests.nix { }; 579 version = testers.testVersion { 580 package = home-assistant; 581 command = "hass --version"; 582 }; 583 withoutCheckDeps = home-assistant.overridePythonAttrs { 584 pname = "home-assistant-without-check-deps"; 585 doCheck = false; 586 }; 587 }; 588 }; 589 590 meta = with lib; { 591 homepage = "https://home-assistant.io/"; 592 changelog = "https://github.com/home-assistant/core/releases/tag/${src.tag}"; 593 description = "Open source home automation that puts local control and privacy first"; 594 license = licenses.asl20; 595 teams = [ teams.home-assistant ]; 596 platforms = platforms.linux; 597 mainProgram = "hass"; 598 }; 599}