nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 540 lines 16 kB view raw
1{ 2 stdenv, 3 lib, 4 callPackage, 5 fetchFromGitHub, 6 fetchPypi, 7 fetchpatch, 8 python313, 9 replaceVars, 10 ffmpeg-headless, 11 ffmpeg_7-headless, 12 inetutils, 13 nixosTests, 14 home-assistant, 15 testers, 16 17 # Look up dependencies of specified components in component-packages.nix 18 extraComponents ? [ ], 19 20 # Additional packages to add to propagatedBuildInputs 21 extraPackages ? ps: [ ], 22 23 # Override Python packages using 24 # self: super: { pkg = super.pkg.overridePythonAttrs (oldAttrs: { ... }); } 25 # Applied after defaultOverrides 26 packageOverrides ? self: super: { }, 27 28 # Skip pip install of required packages on startup 29 skipPip ? true, 30}: 31 32let 33 defaultOverrides = [ 34 # Override the version of some packages pinned in Home Assistant's setup.py and requirements_all.txt 35 36 (self: super: { 37 aionotion = super.aionotion.overridePythonAttrs rec { 38 version = "2024.03.0"; 39 src = fetchFromGitHub { 40 owner = "bachya"; 41 repo = "aionotion"; 42 tag = version; 43 hash = "sha256-BsbfLb5wCVxR8v2U2Zzt7LMl7XJcZWfVjZN47VDkhFc="; 44 }; 45 postPatch = null; 46 }; 47 48 aioskybell = super.aioskybell.overridePythonAttrs (oldAttrs: rec { 49 version = "22.7.0"; 50 src = fetchFromGitHub { 51 owner = "tkdrob"; 52 repo = "aioskybell"; 53 tag = 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 tag = 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 imageio = super.imageio.overridePythonAttrs (oldAttrs: { 91 disabledTests = oldAttrs.disabledTests or [ ] ++ [ 92 # broken by pyav pin 93 "test_keyframe_intervals" 94 "test_lagging_video_stream" 95 ]; 96 }); 97 98 google-genai = super.google-genai.overridePythonAttrs rec { 99 version = "1.38.0"; 100 src = fetchFromGitHub { 101 owner = "googleapis"; 102 repo = "python-genai"; 103 tag = "v${version}"; 104 hash = "sha256-gJaLEpNKHl6n1MvQDIUW7ynsHYH2eEPGsYso5jSysNg="; 105 }; 106 }; 107 108 gspread = super.gspread.overridePythonAttrs (oldAttrs: rec { 109 version = "5.12.4"; 110 src = fetchFromGitHub { 111 owner = "burnash"; 112 repo = "gspread"; 113 tag = "v${version}"; 114 hash = "sha256-i+QbnF0Y/kUMvt91Wzb8wseO/1rZn9xzeA5BWg1haks="; 115 }; 116 dependencies = with self; [ 117 requests 118 ]; 119 }); 120 121 livisi = super.livisi.overridePythonAttrs (oldAttrs: rec { 122 version = "0.0.25"; 123 src = fetchFromGitHub { 124 owner = "planbnet"; 125 repo = "livisi"; 126 tag = "v${version}"; 127 hash = "sha256-kEkbuZmYzxhrbTdo7eZJYu2N2uJtfspgqepplXvSXFg="; 128 }; 129 }); 130 131 notifications-android-tv = super.notifications-android-tv.overridePythonAttrs (oldAttrs: rec { 132 version = "0.1.5"; 133 format = "setuptools"; 134 pyproject = null; 135 136 src = fetchFromGitHub { 137 owner = "engrbm87"; 138 repo = "notifications_android_tv"; 139 tag = version; 140 hash = "sha256-adkcUuPl0jdJjkBINCTW4Kmc16C/HzL+jaRZB/Qr09A="; 141 }; 142 143 nativeBuildInputs = with self; [ 144 setuptools 145 ]; 146 147 propagatedBuildInputs = with self; [ 148 requests 149 ]; 150 151 doCheck = false; # no tests 152 }); 153 154 openhomedevice = super.openhomedevice.overridePythonAttrs (oldAttrs: rec { 155 version = "2.2"; 156 src = fetchFromGitHub { 157 inherit (oldAttrs.src) owner repo; 158 tag = version; 159 hash = "sha256-GGp7nKFH01m1KW6yMkKlAdd26bDi8JDWva6OQ0CWMIw="; 160 }; 161 }); 162 163 plexapi = super.plexapi.overrideAttrs (oldAttrs: rec { 164 version = "4.15.16"; 165 src = fetchFromGitHub { 166 owner = "pkkid"; 167 repo = "python-plexapi"; 168 tag = version; 169 hash = "sha256-NwGGNN6LC3gvE8zoVL5meNWMbqZjJ+6PcU2ebJTfJmU="; 170 }; 171 }); 172 173 # Pinned due to API changes in 0.1.0 174 poolsense = super.poolsense.overridePythonAttrs (oldAttrs: rec { 175 version = "0.0.8"; 176 src = fetchPypi { 177 pname = "poolsense"; 178 inherit version; 179 hash = "sha256-17MHrYRmqkH+1QLtgq2d6zaRtqvb9ju9dvPt9gB2xCc="; 180 }; 181 }); 182 183 py-madvr2 = super.py-madvr2.overridePythonAttrs (oldAttrs: rec { 184 version = "1.6.40"; 185 src = fetchFromGitHub { 186 owner = "iloveicedgreentea"; 187 repo = "py-madvr"; 188 tag = "v${version}"; 189 hash = "sha256-0IX57Sa/oXGiViD39FVBRa2jxuKuZ3UNsOTHwuBdmWs="; 190 }; 191 pythonImportsCheck = [ "madvr" ]; 192 disabledTests = oldAttrs.disabledTests ++ [ 193 "test_async_add_tasks" 194 "test_send_heartbeat" 195 ]; 196 }); 197 198 # Pinned due to API changes >0.3.5.3 199 pyatag = super.pyatag.overridePythonAttrs (oldAttrs: rec { 200 version = "0.3.5.3"; 201 src = fetchFromGitHub { 202 owner = "MatsNl"; 203 repo = "pyatag"; 204 rev = version; 205 sha256 = "00ly4injmgrj34p0lyx7cz2crgnfcijmzc0540gf7hpwha0marf6"; 206 }; 207 }); 208 209 pydexcom = super.pydexcom.overridePythonAttrs (oldAttrs: rec { 210 version = "0.2.3"; 211 src = fetchFromGitHub { 212 owner = "gagebenne"; 213 repo = "pydexcom"; 214 tag = version; 215 hash = "sha256-ItDGnUUUTwCz4ZJtFVlMYjjoBPn2h8QZgLzgnV2T/Qk="; 216 }; 217 }); 218 219 pyflume = super.pyflume.overridePythonAttrs (oldAttrs: rec { 220 version = "0.6.5"; 221 src = fetchFromGitHub { 222 owner = "ChrisMandich"; 223 repo = "PyFlume"; 224 tag = "v${version}"; 225 hash = "sha256-kIE3y/qlsO9Y1MjEQcX0pfaBeIzCCHk4f1Xa215BBHo="; 226 }; 227 dependencies = oldAttrs.propagatedBuildInputs or [ ] ++ [ 228 self.pytz 229 ]; 230 }); 231 232 pysnooz = super.pysnooz.overridePythonAttrs (oldAttrs: rec { 233 version = "0.8.6"; 234 src = fetchFromGitHub { 235 owner = "AustinBrunkhorst"; 236 repo = "pysnooz"; 237 tag = "v${version}"; 238 hash = "sha256-hJwIObiuFEAVhgZXYB9VCeAlewBBnk0oMkP83MUCpyU="; 239 }; 240 patches = [ ]; 241 doCheck = false; 242 }); 243 244 pytradfri = super.pytradfri.overridePythonAttrs (oldAttrs: rec { 245 version = "9.0.1"; 246 src = fetchFromGitHub { 247 owner = "home-assistant-libs"; 248 repo = "pytradfri"; 249 tag = version; 250 hash = "sha256-xOdTzG0bF5p1QpkXv2btwrVugQRjSwdAj8bXcC0IoQg="; 251 }; 252 patches = [ ]; 253 doCheck = false; 254 }); 255 256 wolf-comm = super.wolf-comm.overridePythonAttrs rec { 257 version = "0.0.23"; 258 src = fetchFromGitHub { 259 owner = "janrothkegel"; 260 repo = "wolf-comm"; 261 tag = version; 262 hash = "sha256-LpehooW3vmohiyMwOQTFNLiNCsaLKelWQxQk8bl+y1k="; 263 }; 264 }; 265 266 # internal python packages only consumed by home-assistant itself 267 hass-web-proxy-lib = self.callPackage ./python-modules/hass-web-proxy-lib { }; 268 home-assistant-frontend = self.callPackage ./frontend.nix { }; 269 home-assistant-intents = self.callPackage ./intents.nix { }; 270 homeassistant = self.toPythonModule home-assistant; 271 pytest-homeassistant-custom-component = 272 self.callPackage ./pytest-homeassistant-custom-component.nix 273 { }; 274 }) 275 ]; 276 277 python = python313.override { 278 self = python; 279 packageOverrides = lib.composeManyExtensions (defaultOverrides ++ [ packageOverrides ]); 280 }; 281 282 componentPackages = import ./component-packages.nix; 283 284 availableComponents = builtins.attrNames componentPackages.components; 285 286 inherit (componentPackages) supportedComponentsWithTests; 287 288 getPackages = component: componentPackages.components.${component}; 289 290 componentBuildInputs = lib.concatMap (component: getPackages component python.pkgs) extraComponents; 291 292 # Ensure that we are using a consistent package set 293 extraBuildInputs = extraPackages python.pkgs; 294 295 # Don't forget to run update-component-packages.py after updating 296 hassVersion = "2026.1.3"; 297 298in 299python.pkgs.buildPythonApplication rec { 300 pname = "homeassistant"; 301 version = 302 assert (componentPackages.version == hassVersion); 303 hassVersion; 304 pyproject = true; 305 306 # check REQUIRED_PYTHON_VER in homeassistant/const.py 307 disabled = python.pythonOlder "3.13"; 308 309 # don't try and fail to strip 6600+ python files, it takes minutes! 310 dontStrip = true; 311 312 # Primary source is the git, which has the tests and allows bisecting the core 313 src = fetchFromGitHub { 314 owner = "home-assistant"; 315 repo = "core"; 316 tag = version; 317 hash = "sha256-zmS5OZaUFe45rbCil7sbVlhy0wwA+F9tBO10KvBM2PY="; 318 }; 319 320 # Secondary source is pypi sdist for translations 321 sdist = fetchPypi { 322 inherit pname version; 323 hash = "sha256-gs5YyR1MofSMV8TDeBGp9keIREcszZGcLvtnHOYR7uc="; 324 }; 325 326 build-system = with python.pkgs; [ 327 setuptools 328 ]; 329 330 pythonRelaxDeps = true; 331 332 # extract translations from pypi sdist 333 prePatch = '' 334 tar --extract --gzip --file $sdist --strip-components 1 --wildcards "**/translations" 335 ''; 336 337 # leave this in, so users don't have to constantly update their downstream patch handling 338 patches = [ 339 # Follow symlinks in /var/lib/hass/www 340 ./patches/static-follow-symlinks.patch 341 342 # Copy default blueprints without preserving permissions 343 ./patches/default-blueprint-permissions.patch 344 345 # Patch path to ffmpeg binary 346 (replaceVars ./patches/ffmpeg-path.patch { 347 ffmpeg = "${lib.getExe ffmpeg-headless}"; 348 }) 349 350 (fetchpatch { 351 # pytest 9 renames some snapshots 352 name = "revert-to-pytest-8.patch"; 353 url = "https://github.com/home-assistant/core/commit/3f22dbaa2e1a7776185ec443bf26f90e90e55efa.patch"; 354 revert = true; 355 hash = "sha256-rHXpmHUNCr+lhYqiOVrCSQTWvWJ+jHNwPJzUeFtDPIw="; 356 }) 357 ]; 358 359 postPatch = '' 360 substituteInPlace tests/test_core_config.py --replace-fail '"/usr"' "\"$NIX_BUILD_TOP/media\"" 361 362 substituteInPlace pyproject.toml \ 363 --replace-fail "setuptools==78.1.1" setuptools 364 ''; 365 366 pythonRemoveDeps = [ 367 "uv" 368 ]; 369 370 dependencies = with python.pkgs; [ 371 # Only packages required in pyproject.toml 372 aiodns 373 aiohasupervisor 374 aiohttp 375 aiohttp-asyncmdnsresolver 376 aiohttp-cors 377 aiohttp-fast-zlib 378 aiozoneinfo 379 annotatedyaml 380 astral 381 async-interrupt 382 atomicwrites-homeassistant 383 attrs 384 audioop-lts 385 awesomeversion 386 bcrypt 387 certifi 388 ciso8601 389 cronsim 390 cryptography 391 fnv-hash-fast 392 hass-nabucasa 393 home-assistant-bluetooth 394 httpx 395 ifaddr 396 jinja2 397 lru-dict 398 orjson 399 packaging 400 pillow 401 propcache 402 psutil-home-assistant 403 pyjwt 404 pyopenssl 405 python-slugify 406 pyyaml 407 requests 408 securetar 409 sqlalchemy 410 standard-aifc 411 standard-telnetlib 412 typing-extensions 413 ulid-transform 414 urllib3 415 voluptuous 416 voluptuous-openapi 417 voluptuous-serialize 418 webrtc-models 419 yarl 420 zeroconf 421 # REQUIREMENTS in homeassistant/auth/mfa_modules/totp.py and homeassistant/auth/mfa_modules/notify.py 422 pyotp 423 pyqrcode 424 ]; 425 426 makeWrapperArgs = lib.optional skipPip "--add-flags --skip-pip"; 427 428 # upstream only tests on Linux, so do we. 429 doCheck = stdenv.hostPlatform.isLinux; 430 431 requirementsTest = with python.pkgs; [ 432 # test infrastructure (selectively from requirement_test.txt) 433 freezegun 434 pytest-asyncio 435 pytest-aiohttp 436 pytest-freezer 437 pytest-socket 438 pytest-timeout 439 pytest-unordered 440 pytest-xdist 441 pytestCheckHook 442 requests-mock 443 respx 444 syrupy 445 ]; 446 447 nativeCheckInputs = 448 requirementsTest 449 ++ (with python.pkgs; [ 450 # Used in tests/non_packaged_scripts/test_alexa_locales.py 451 beautifulsoup4 452 # Used in tests/scripts/test_check_config.py 453 colorlog 454 ]) 455 ++ lib.concatMap (component: getPackages component python.pkgs) [ 456 # some components are needed even if tests in tests/components are disabled 457 "assist_pipeline" 458 "frontend" 459 "hue" 460 "mobile_app" 461 ]; 462 463 pytestFlags = [ 464 # assign tests grouped by file to workers 465 "--dist=loadfile" 466 # enable full variable printing on error 467 "--showlocals" 468 ]; 469 470 enabledTestPaths = [ 471 # tests are located in tests/ 472 "tests" 473 ]; 474 475 disabledTestPaths = [ 476 # we neither run nor distribute hassfest 477 "tests/hassfest" 478 # we don't care about code quality 479 "tests/pylint" 480 # redundant component import test, which would make debugpy & sentry expensive to review 481 "tests/test_circular_imports.py" 482 # don't bulk test all components 483 "tests/components" 484 # AssertionError: assert 1 == 0 485 "tests/test_config.py::test_merge" 486 # checks whether pip is installed 487 "tests/util/test_package.py::test_check_package_fragment" 488 # flaky 489 "tests/test_bootstrap.py::test_setup_hass_takes_longer_than_log_slow_startup" 490 "tests/test_test_fixtures.py::test_evict_faked_translations" 491 "tests/helpers/test_backup.py::test_async_get_manager" 492 "tests/helpers/test_trigger.py::test_platform_multiple_triggers[sync_action]" 493 ]; 494 495 preCheck = '' 496 export HOME="$TEMPDIR" 497 export PYTHONASYNCIODEBUG=1 498 499 # the tests require the existance of a media dir 500 mkdir "$NIX_BUILD_TOP"/media 501 502 # put ping binary into PATH, e.g. for wake_on_lan tests 503 export PATH=${inetutils}/bin:$PATH 504 ''; 505 506 passthru = { 507 inherit 508 availableComponents 509 extraComponents 510 getPackages 511 python 512 supportedComponentsWithTests 513 ; 514 pythonPath = python.pkgs.makePythonPath (componentBuildInputs ++ extraBuildInputs); 515 frontend = python.pkgs.home-assistant-frontend; 516 intents = python.pkgs.home-assistant-intents; 517 tests = { 518 nixos = nixosTests.home-assistant; 519 components = callPackage ./tests.nix { }; 520 version = testers.testVersion { 521 package = home-assistant; 522 command = "hass --version"; 523 }; 524 withoutCheckDeps = home-assistant.overridePythonAttrs { 525 pname = "home-assistant-without-check-deps"; 526 doCheck = false; 527 }; 528 }; 529 }; 530 531 meta = { 532 homepage = "https://home-assistant.io/"; 533 changelog = "https://github.com/home-assistant/core/releases/tag/${src.tag}"; 534 description = "Open source home automation that puts local control and privacy first"; 535 license = lib.licenses.asl20; 536 teams = [ lib.teams.home-assistant ]; 537 platforms = lib.platforms.linux; 538 mainProgram = "hass"; 539 }; 540}