Compare commits

...

54 Commits

Author SHA1 Message Date
Sandro Jäckel
64b0db6e10 python3Packages.pystiebeleltron: 0.9.2 -> 0.10.1
Diff: https://github.com/ThyMYthOS/python-stiebel-eltron/compare/v0.9.2...v0.10.1

Changelog: https://github.com/ThyMYthOS/python-stiebel-eltron/releases/tag/v0.10.1
2026-11-05 21:21:01 +01:00
Sandro Jäckel
6f3c9b219e python3Packages.python-kasa: 0.11.0.1 -> 0.12.0
Diff: https://github.com/python-kasa/python-kasa/compare/0.11.0.1...0.12.0

Changelog: https://github.com/python-kasa/python-kasa/blob/0.12.0/CHANGELOG.md
2026-11-05 21:07:19 +01:00
Sandro Jäckel
c0d1285f41 python3Packages.python-qube-heatpump: 1.15.0 -> 1.17.0
Diff: https://github.com/MattieGit/python-qube-heatpump/compare/v1.15.0...v1.17.0

Changelog: https://github.com/MattieGit/python-qube-heatpump/releases/tag/v1.17.0
2026-11-05 21:07:18 +01:00
Sandro Jäckel
85d82c7a0b python3Packages.python-openevse-http: 1.5.0 -> 1.8.0
Diff: https://github.com/firstof9/python-openevse-http/compare/1.5.0...1.8.0

Changelog: https://github.com/firstof9/python-openevse-http/releases/tag/1.8.0
2026-11-05 21:07:18 +01:00
R. Ryantm
b0a03543a8 python3Packages.python-bsblan: 6.1.9 -> 6.2.1 2026-11-05 21:07:02 +01:00
Sandro Jäckel
6a0bf99af5 python3Packages.sense-energy: 0.14.3 -> 0.15.0
Diff: https://github.com/scottbonline/sense/compare/0.14.3...0.15.0

Changelog: https://github.com/scottbonline/sense/releases/tag/0.15.0
2026-11-05 20:35:44 +01:00
Sandro Jäckel
9a5db4ef77 python3Packages.sofar-modbus: 0.18.0 -> 0.25.3
Diff: https://github.com/darkrain-nl/sofar-modbus/compare/0.18.0...0.25.3

Changelog: https://github.com/darkrain-nl/sofar-modbus/releases/tag/0.25.3
2026-11-05 20:29:00 +01:00
Sandro Jäckel
f19359bb9b python3Packages.securetar: 2026.4.1 -> 2026.10.0
Diff: https://github.com/home-assistant-libs/securetar/compare/2026.4.1...2026.10.0

Changelog: https://github.com/home-assistant-libs/securetar/releases/tag/2026.10.0
2026-11-05 20:27:03 +01:00
Sandro Jäckel
864ccdc6d9 python3Packages.samsungtvws: 3.0.6 -> 3.0.7
Diff: https://github.com/xchwarze/samsung-tv-ws-api/compare/v3.0.6...v3.0.7

Changelog: https://github.com/xchwarze/samsung-tv-ws-api/releases/tag/v3.0.7
2026-11-05 20:23:10 +01:00
Sandro Jäckel
283f7cece0 python3Packages.adguardhome: 0.8.1 -> 1.0.0
Diff: https://github.com/frenck/python-adguardhome/compare/v0.8.1...v1.0.0

Changelog: https://github.com/frenck/python-adguardhome/releases/tag/v1.0.0
2026-11-05 20:21:14 +01:00
Sandro Jäckel
7f6ab4f8b6 python3Packages.aio-ownet: 0.0.5 -> 0.1.0
Diff: https://github.com/hacf-fr/aio-ownet/compare/v0.0.5...v0.1.0

Changelog: https://github.com/hacf-fr/aio-ownet/releases/tag/v0.1.0
2026-11-05 19:45:43 +01:00
Fabian Affolter
e0abd133ad python3Packages.aio-wattwaechter: 1.1.0 -> 1.3.0
Changelog: https://github.com/SmartCircuits-GmbH/WattWaechter-PyPI/releases/tag/v1.3.0
2026-11-05 19:36:11 +01:00
Sandro Jäckel
e8157e600c python3Packages.aioamazondevices: 16.3.2 -> 17.2.4
Diff: https://github.com/chemelli74/aioamazondevices/compare/v16.3.2...v17.2.4

Changelog: https://github.com/chemelli74/aioamazondevices/blob/v17.2.4/CHANGELOG.md
2026-11-05 19:31:22 +01:00
Robert Schütz
ac729f3bad python3Packages.aioesphomeapi: 46.23.0 -> 46.27.0
Diff: https://github.com/esphome/aioesphomeapi/compare/v46.23.0...v46.27.0

Changelog: https://github.com/esphome/aioesphomeapi/releases/tag/v46.27.0
2026-11-05 19:17:28 +01:00
Robert Schütz
526d05ebd6 python3Packages.zeroconf: 0.151.5 -> 0.153.0
Diff: https://github.com/jstasiak/python-zeroconf/compare/0.151.5...0.153.0

Changelog: https://github.com/python-zeroconf/python-zeroconf/blob/0.153.0/CHANGELOG.md
2026-11-05 19:13:13 +01:00
Sandro Jäckel
76f2f572fe python3Packages.aiopowerwall: 0.4.1 -> 0.10.0
Diff: https://github.com/Teslemetry/aiopowerwall/compare/v0.4.1...v0.10.0

Changelog: https://github.com/Teslemetry/aiopowerwall/releases/tag/v0.10.0
2026-11-05 19:12:33 +01:00
Sandro Jäckel
e5fcd544bf python3Packages.tesla-protocol: 3.0.2 -> 4.0.1
Diff: https://github.com/Teslemetry/tesla-protocol/compare/@teslemetry/tesla-protocol@3.0.2...@teslemetry/tesla-protocol@4.0.1

Changelog: https://github.com/Teslemetry/tesla-protocol/releases/tag/@teslemetry/tesla-protocol@4.0.1
2026-11-05 19:12:32 +01:00
Fabian Affolter
fc388689aa python3Packages.aiomealie: 2.1.2 -> 2.1.3
Diff: https://github.com/joostlek/python-mealie/compare/v2.1.2...v2.1.3

Changelog: https://github.com/joostlek/python-mealie/releases/tag/v2.1.3
2026-11-05 19:12:32 +01:00
Sandro Jäckel
747a955030 python3Packages.aiovodafone: 3.3.5 -> 3.3.11
Changelog: https://github.com/chemelli74/aiovodafone/blob/v3.3.11/CHANGELOG.md
2026-11-05 19:12:32 +01:00
Sandro Jäckel
8d1df0105c python3Packages.aioslimproto: 3.2.3 -> 3.3.0
Diff: https://github.com/home-assistant-libs/aioslimproto/compare/3.2.3...3.3.0

Changelog: https://github.com/home-assistant-libs/aioslimproto/releases/tag/3.3.0
2026-11-05 19:12:31 +01:00
Sandro Jäckel
baccdab2c2 python3Packages.aioswitcher: 6.3.0 -> 6.4.0
Diff: https://github.com/TomerFi/aioswitcher/compare/6.3.0...6.4.0

Changelog: https://github.com/TomerFi/aioswitcher/releases/tag/6.4.0
2026-11-05 19:12:31 +01:00
Sandro Jäckel
e4d1530f1c python3Packages.getmac: 0.9.5 -> 0.9.6
Diff: https://github.com/GhostofGoes/getmac/compare/0.9.5...0.9.6

Changelog: https://github.com/GhostofGoes/getmac/blob/0.9.6/CHANGELOG.md
2026-11-05 19:12:30 +01:00
Sandro Jäckel
03ea925282 python3Packages.mastodon-py: 2.2.2 -> 2.3.3
Diff: https://github.com/halcy/Mastodon.py/compare/v2.2.2...v2.3.3

Changelog: https://github.com/halcy/Mastodon.py/blob/v2.3.3/CHANGELOG.rst
2026-11-05 19:12:30 +01:00
Sandro Jäckel
a04dd970dc python3Packages.govee-local-api: 3.1.0 -> 3.3.1
Diff: https://github.com/Galorhallen/govee-local-api/compare/v3.1.0...v3.3.1

Changelog: https://github.com/Galorhallen/govee-local-api/releases/tag/v3.3.1
2026-11-05 19:12:30 +01:00
Fabian Affolter
15c56829d3 python3Packages.airgradient: 0.10.0 -> 0.11.0
Diff: https://github.com/airgradienthq/python-airgradient/compare/v0.10.0...v0.11.0

Changelog: https://github.com/airgradienthq/python-airgradient/releases/tag/v0.11.0
2026-11-05 19:12:29 +01:00
Robert Schütz
0f01130789 python3Packages.paho-mqtt: use finalAttrs 2026-11-05 19:12:29 +01:00
Robert Schütz
72152964c4 python3Packages.paho-mqtt: 2.1.0 -> 2.2.0
Diff: https://github.com/eclipse/paho.mqtt.python/compare/v2.1.0...v2.2.0

Changelog: https://github.com/eclipse/paho.mqtt.python/blob/v2.2.0/ChangeLog.txt
2026-11-05 19:12:28 +01:00
Sandro Jäckel
5eea90ff0b fixup! home-assistant: 2026.10.4 -> 2026.11.0 2026-11-05 19:12:28 +01:00
Sandro Jäckel
9fdd8f7e0e python3Packages.midea-local: 12.2.0 -> 15.0.0
Diff: https://github.com/midea-lan/midea-local/compare/v12.2.0...v15.0.0

Changelog: https://github.com/midea-lan/midea-local/releases/tag/v15.0.0
2026-11-05 19:12:28 +01:00
Sandro Jäckel
a6c56e5362 python3Packages.music-assistant-client: 1.5.1 -> 1.6.0
Diff: https://github.com/music-assistant/client/compare/v1.5.1...v1.6.0

Changelog: https://github.com/music-assistant/client/releases/tag/v1.6.0
2026-11-05 19:12:27 +01:00
Sandro Jäckel
1634d8d9d2 python3Packages.music-assistant-models: 1.1.189 -> 1.1.214
Diff: https://github.com/music-assistant/models/compare/1.1.189...1.1.214

Changelog: https://github.com/music-assistant/models/releases/tag/1.1.214
2026-11-05 19:12:27 +01:00
Sandro Jäckel
f49a1ca855 python3Packages.open-meteo: 0.4.0 -> 1.0.1
Diff: https://github.com/frenck/python-open-meteo/compare/v0.4.0...v1.0.1

Changelog: https://github.com/frenck/python-open-meteo/releases/tag/1.0.1
2026-11-05 19:12:26 +01:00
Sandro Jäckel
bc1e022af2 python3Packages.python-open-router: 0.4.0 -> 0.5.0
Diff: https://github.com/joostlek/python-open-router/compare/v0.4.0...v0.5.0

Changelog: https://github.com/joostlek/python-open-router/releases/tag/v0.5.0
2026-11-05 19:12:26 +01:00
Sandro Jäckel
911197569e python3Packages.pyblu: 2.1.0 -> 2.2.0
Diff: https://github.com/LouisChrist/pyblu/compare/v2.1.0...v2.2.0

Changelog: https://github.com/LouisChrist/pyblu/releases/tag/v2.2.0
2026-11-05 19:12:26 +01:00
Sandro Jäckel
cdf76905ce python3Packages.universal-silabs-flasher: 1.1.0 -> 1.3.0
Diff: https://github.com/NabuCasa/universal-silabs-flasher/compare/v1.1.0...v1.3.0

Changelog: https://github.com/NabuCasa/universal-silabs-flasher/releases/tag/v1.3.0
2026-11-05 19:12:25 +01:00
Sandro Jäckel
a5a8f40628 python3Packages.aiospinel: 1.2.0 -> 1.3.0
Diff: https://github.com/home-assistant-libs/aiospinel/compare/v1.2.0...v1.3.0

Changelog: https://github.com/home-assistant-libs/aiospinel/releases/tag/v1.3.0
2026-11-05 19:12:25 +01:00
Sandro Jäckel
8df6f8dd87 python3Packages.hass-nabucasa: 2.7.0 -> 2.8.1
Diff: https://github.com/nabucasa/hass-nabucasa/compare/2.7.0...2.8.1

Changelog: https://github.com/NabuCasa/hass-nabucasa/releases/tag/2.8.1
2026-11-05 19:12:24 +01:00
Sandro Jäckel
873bf1e8d6 python3Packages.soco: 0.31.4 -> 0.32.1
Diff: https://github.com/SoCo/SoCo/compare/v0.31.4...v0.32.1

Changelog: https://github.com/SoCo/SoCo/releases/tag/v0.32.1
2026-11-05 19:12:24 +01:00
Sandro Jäckel
bb62ba29b9 python3Packages.aiohasupervisor: 0.6.0 -> 0.8.1
Diff: https://github.com/home-assistant-libs/python-supervisor-client/compare/0.6.0...0.8.1

Changelog: https://github.com/home-assistant-libs/python-supervisor-client/releases/tag/0.8.1
2026-11-05 19:12:24 +01:00
Sandro Jäckel
e79c2ec8df python3Packages.zha-quirks: 2.3.0 -> 2.4.1
Changelog: https://github.com/zigpy/zha-device-handlers/releases/tag/2.4.1
Diff: https://github.com/zigpy/zha-device-handlers/compare/2.3.0...2.4.1
2026-11-05 16:19:38 +01:00
Sandro Jäckel
5ca2a69844 python3Packages.zha: 2.3.1 -> 2.4.2
Diff: https://github.com/zigpy/zha/compare/2.3.1...2.4.2

Changelog: https://github.com/zigpy/zha/releases/tag/2.4.2
2026-11-05 16:14:05 +01:00
Sandro Jäckel
6457f3a943 python3Packages.zigpy-deconz: 1.0.0 -> 1.1.1
Diff: https://github.com/zigpy/zigpy-deconz/compare/1.0.0...1.1.1

Changelog: https://github.com/zigpy/zigpy-deconz/releases/tag/1.1.1
2026-11-05 16:08:44 +01:00
Sandro Jäckel
77ff7866a8 python3Packages.zigpy-znp: fix compatibility with zigpy 2.4.1 2026-11-05 16:06:33 +01:00
Sandro Jäckel
00b3cb7239 python3Packages.zigpy-ziggurat: 1.1.1 -> 1.2.0
Diff: https://github.com/zigpy/zigpy-ziggurat/compare/v1.1.1...v1.2.0

Changelog: https://github.com/zigpy/zigpy-ziggurat/releases/tag/v1.2.0
2026-11-05 16:01:35 +01:00
Sandro Jäckel
a4205f5922 python3Packages.bellows: 1.1.0 -> 1.2.1
Diff: https://github.com/zigpy/bellows/compare/1.1.0...1.2.1

Changelog: https://github.com/zigpy/bellows/releases/tag/1.2.1
2026-11-05 16:01:35 +01:00
Sandro Jäckel
1380c33506 python3Packages.zigpy: 2.3.0 -> 2.4.1
Changelog: https://github.com/zigpy/zigpy/releases/tag/2.4.0
Changelog: https://github.com/zigpy/zigpy/releases/tag/2.4.1
Diff: https://github.com/zigpy/zigpy/compare/2.3.0...2.4.1
2026-11-05 16:01:18 +01:00
Fabian Affolter
25f411ca5a python3Packages.aiosqlite: migrate to finalAttrs 2026-11-05 15:39:12 +01:00
Fabian Affolter
f239ff4bff python3Packages.aiosqlite: 0.21.0 -> 0.22.1
Diff: https://github.com/omnilib/aiosqlite/compare/v0.21.0...v0.22.1

Changelog: https://github.com/omnilib/aiosqlite/blob/v0.22.1/CHANGELOG.md
2026-11-05 15:35:41 +01:00
Sandro Jäckel
6a38ccab79 fixup! home-assistant: 2026.10.4 -> 2026.11.0 2026-11-05 15:24:56 +01:00
Sandro Jäckel
5adf66627a python3Packages.pygbl: init at 1.2.0 2026-11-05 15:20:10 +01:00
dotlambda
a3f1a4bec9 python3Packages.nextdns: 5.1.0 -> 5.2.0 (#580735) 2026-11-04 16:49:11 -08:00
Robert Schütz
75303e4989 fixup! home-assistant: 2026.10.4 -> 2026.11.0 2026-11-04 14:10:00 -08:00
Martin Weinelt
f560255820 home-assistant: 2026.10.4 -> 2026.11.0 2026-11-04 22:33:52 +01:00
Fabian Affolter
c3153ea069 python3Packages.nextdns: 5.1.0 -> 5.2.0
Diff: https://github.com/bieniu/nextdns/compare/5.1.0...5.2.0

Changelog: https://github.com/bieniu/nextdns/releases/tag/5.2.0
2026-10-30 00:59:18 +01:00
60 changed files with 1495 additions and 447 deletions

View File

@@ -1,45 +1,77 @@
{
lib,
aiohttp,
aresponses,
aiointercept,
awesomeversion,
buildPythonPackage,
click,
fetchFromGitHub,
mashumaro,
orjson,
poetry-core,
pyprojectVersionPatchHook,
pytest-asyncio,
pytest-cov-stub,
pytestCheckHook,
rich,
syrupy,
typer,
yarl,
}:
buildPythonPackage (finalAttrs: {
pname = "adguardhome";
version = "0.8.1";
version = "1.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "frenck";
repo = "python-adguardhome";
tag = "v${finalAttrs.version}";
hash = "sha256-pc7UfR/0mQZ98FyomQErz5hePHy6KE2h9UhJ9lFGtFA=";
hash = "sha256-UpRr1HTh7BMNWL4ml6pWe+AsIy4MEgTpa4HgdzH36oQ=";
};
patches = [
# https://github.com/frenck/python-adguardhome/pull/1870
./typer-0.26.patch
];
build-system = [ poetry-core ];
nativeBuildInputs = [ pyprojectVersionPatchHook ];
dependencies = [
aiohttp
awesomeversion
mashumaro
orjson
yarl
];
optional-dependencies = {
cli = [
rich
typer
];
};
__darwinAllowLocalNetworking = true;
nativeCheckInputs = [
aresponses
aiointercept
pytest-asyncio
pytest-cov-stub
pytestCheckHook
syrupy
]
++ finalAttrs.passthru.optional-dependencies.cli;
disabledTests = [
# fixture formatting differs
"test_config"
"test_get"
"test_stats"
"test_status"
];
pythonImportsCheck = [ "adguardhome" ];

View File

@@ -0,0 +1,40 @@
commit 22a786da1047189825233c293dd5fc2a129fd8ea
Author: Sandro Jäckel <sandro.jaeckel@gmail.com>
Date: Thu, 5 Nov 2026 20:02:33 +0100
Fix CLI structure test with typer 0.26
diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py
index 74d842f..9264105 100644
--- a/tests/cli/test_cli.py
+++ b/tests/cli/test_cli.py
@@ -10,9 +10,10 @@
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock, MagicMock
-import click
import pytest
from awesomeversion import AwesomeVersion
+from typer import BadParameter
+from typer.core import TyperGroup
from typer.main import get_command
from typer.testing import CliRunner
@@ -80,7 +81,7 @@ def client(monkeypatch: pytest.MonkeyPatch) -> AsyncMock:
def test_cli_structure(snapshot: SnapshotAssertion) -> None:
"""Test the commands and their parameters stay as they are."""
command = get_command(cli)
- assert isinstance(command, click.Group)
+ assert isinstance(command, TyperGroup)
structure = {
name: sorted(param.name for param in sub.params if param.name)
@@ -279,7 +280,7 @@ def test_parse_duration(value: str, expected: timedelta) -> None:
)
def test_parse_duration_invalid(value: str, message: str) -> None:
"""Test values that are not a positive duration are rejected."""
- with pytest.raises(click.BadParameter, match=message):
+ with pytest.raises(BadParameter, match=message):
parse_duration(value)

View File

@@ -1,33 +1,40 @@
{
buildPythonPackage,
click,
fetchFromGitHub,
lib,
poetry-core,
buildPythonPackage,
fetchFromGitHub,
pyprojectVersionPatchHook,
pytest-asyncio,
pytestCheckHook,
uv-build,
}:
buildPythonPackage rec {
pname = "aio-ownet";
version = "0.0.5";
version = "0.1.0";
pyproject = true;
src = fetchFromGitHub {
owner = "hacf-fr";
repo = "aio-ownet";
tag = "v${version}";
hash = "sha256-KgQasltfoffVjCDX9s98qnZrv+VLiEffLi9FnUD5vXc=";
hash = "sha256-+RIfCtLQu2OBBlj5Lcd7/iiXMuSlvJq3EcXBaXw4T1I=";
};
build-system = [ poetry-core ];
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "uv_build>=0.12.21,<0.13" "uv_build"
'';
optional-dependencies = {
cli = [ click ];
};
nativeBuildInputs = [
pyprojectVersionPatchHook
];
build-system = [ uv-build ];
pythonImportsCheck = [ "aio_ownet" ];
nativeCheckInputs = [
pytest-asyncio
pytestCheckHook
];

View File

@@ -11,14 +11,14 @@
buildPythonPackage (finalAttrs: {
pname = "aio-wattwaechter";
version = "1.1.0";
version = "1.3.0";
pyproject = true;
src = fetchFromGitHub {
owner = "SmartCircuits-GmbH";
repo = "WattWaechter-PyPI";
tag = "v${finalAttrs.version}";
hash = "sha256-hM2DGQBEUr1HYd0CDdjRdFA7+HKaF2kLVFrAWCjP+CU=";
hash = "sha256-jpLyBjgjtqFn9BNNOXs7cR4uk6y174HKjulYFf0sDj4=";
};
build-system = [ setuptools ];

View File

@@ -1,5 +1,6 @@
{
aiohttp,
anyio,
beautifulsoup4,
buildPythonPackage,
fetchFromGitHub,
@@ -15,20 +16,29 @@
buildPythonPackage (finalAttrs: {
pname = "aioamazondevices";
version = "16.3.2";
version = "17.2.4";
pyproject = true;
src = fetchFromGitHub {
owner = "chemelli74";
repo = "aioamazondevices";
tag = "v${finalAttrs.version}";
hash = "sha256-2ToEnoaOJvbW/34DsndV2w8qZAfRX0a4tRh5B5k/PNQ=";
hash = "sha256-i2FPhbgy19ixaPEjDm8nCQlQaB2uauZNmA95fb4jPEM=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools>=84.2.1" "setuptools"
'';
# all deps are needlessly pinned to very recent versions
pythonRelaxDeps = true;
build-system = [ poetry-core ];
dependencies = [
aiohttp
anyio
beautifulsoup4
httpx
langcodes

View File

@@ -29,16 +29,21 @@
buildPythonPackage (finalAttrs: {
pname = "aioesphomeapi";
version = "46.23.0"; # must track the major version that home-assistant pins
version = "46.27.0"; # must track the major version that home-assistant pins
pyproject = true;
src = fetchFromGitHub {
owner = "esphome";
repo = "aioesphomeapi";
tag = "v${finalAttrs.version}";
hash = "sha256-7n6K+MY0s2oOvnbUXrZA/PCamfpel1jYZr4RXzH+Y6s=";
hash = "sha256-IRV6yZqP56+3JiY84BQHFsuyj+gOO9gCOvj63uzo+IE=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail 'setuptools>=84.2.0' setuptools
'';
build-system = [
setuptools
cython

View File

@@ -17,19 +17,19 @@
buildPythonPackage rec {
pname = "aiohasupervisor";
version = "0.6.0";
version = "0.8.1";
pyproject = true;
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "python-supervisor-client";
tag = version;
hash = "sha256-OAuLee6hbShgEDN/3oD7O6KzxylnfrJoCgMPjluYcG8=";
hash = "sha256-i6OyDuC+463DbMmTskrXp24ecftRwrQycsQEh9nRmpo=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools>=68.0,<83.1" "setuptools"
--replace-fail "setuptools>=68.0,<84.1" "setuptools"
'';
nativeBuildInputs = [

View File

@@ -18,14 +18,14 @@
buildPythonPackage (finalAttrs: {
pname = "aiomealie";
version = "2.1.2";
version = "2.1.3";
pyproject = true;
src = fetchFromGitHub {
owner = "joostlek";
repo = "python-mealie";
tag = "v${finalAttrs.version}";
hash = "sha256-F9gl+OdTQe6VxZPvFyo8r5GRxO3Ug4juvqje86djFNw=";
hash = "sha256-yf/16+Yi7Wvafl9mH5ah6SYbMtrhIXsn/4ajyjidR+M=";
};
build-system = [ hatchling ];

View File

@@ -13,14 +13,14 @@
buildPythonPackage (finalAttrs: {
pname = "aiopowerwall";
version = "0.4.1";
version = "0.10.0";
pyproject = true;
src = fetchFromGitHub {
owner = "Teslemetry";
repo = "aiopowerwall";
tag = "v${finalAttrs.version}";
hash = "sha256-I1TdmsMgCGzBMAnx+QUTHB4UmxunmYnf+VS11kPrc8o=";
hash = "sha256-be6q7Wn8OMHMPkNJSR/E4Ah0j4Clz9dj1YG4irpLqW8=";
};
build-system = [ hatchling ];

View File

@@ -1,40 +1,44 @@
{
lib,
aiohttp,
async-timeout,
buildPythonPackage,
fetchFromGitHub,
pillow,
pyprojectVersionPatchHook,
pytest-asyncio,
pytest-cov-stub,
pytestCheckHook,
setuptools,
}:
buildPythonPackage (finalAttrs: {
pname = "aioslimproto";
version = "3.2.3";
version = "3.3.0";
pyproject = true;
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "aioslimproto";
tag = finalAttrs.version;
hash = "sha256-TSoVQ1AwJSWAwMKfxZC/9lWyCiMo9Fvq9L0fuyUmAMY=";
hash = "sha256-98GLhv60SaPQIi8OEWTVPz+3TT2rBRuXUKfF/8TG/nU=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail 'version = "0.0.0"' 'version = "${finalAttrs.version}"'
'';
nativeBuildInputs = [
pyprojectVersionPatchHook
];
build-system = [ setuptools ];
dependencies = [
aiohttp
async-timeout
pillow
];
# Module has no tests
doCheck = false;
nativeCheckInputs = [
pytest-asyncio
pytest-cov-stub
pytestCheckHook
];
pythonImportsCheck = [ "aioslimproto" ];

View File

@@ -13,14 +13,14 @@
buildPythonPackage (finalAttrs: {
pname = "aiospinel";
version = "1.2.0";
version = "1.3.0";
pyproject = true;
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "aiospinel";
tag = "v${finalAttrs.version}";
hash = "sha256-AMIrm9AGFjRSDwJtDXcOH9HIBFiqszjjNma+egRa5Tw=";
hash = "sha256-l3RHQVpKJwMRRcC3+NUS650lEv1+gnLfrxjkeToa/I0=";
};
build-system = [

View File

@@ -4,25 +4,22 @@
fetchFromGitHub,
flit-core,
pytestCheckHook,
typing-extensions,
}:
buildPythonPackage rec {
buildPythonPackage (finalAttrs: {
pname = "aiosqlite";
version = "0.21.0";
version = "0.22.1";
pyproject = true;
src = fetchFromGitHub {
owner = "omnilib";
repo = "aiosqlite";
tag = "v${version}";
hash = "sha256-3l/uR97WuLlkAEdogL9iYoXp89bsAcpH6XEtMELsX9o=";
tag = "v${finalAttrs.version}";
hash = "sha256-voOOFo1OwaRQ3JsDHlBrngP+8ajf0kTNKXJyOaJiTs4=";
};
build-system = [ flit-core ];
dependencies = [ typing-extensions ];
nativeCheckInputs = [ pytestCheckHook ];
# Tests are not pick-up automatically by the hook
@@ -33,8 +30,8 @@ buildPythonPackage rec {
meta = {
description = "Asyncio bridge to the standard sqlite3 module";
homepage = "https://github.com/jreese/aiosqlite";
changelog = "https://github.com/omnilib/aiosqlite/blob/${src.tag}/CHANGELOG.md";
changelog = "https://github.com/omnilib/aiosqlite/blob/${finalAttrs.src.tag}/CHANGELOG.md";
license = lib.licenses.mit;
maintainers = [ ];
};
}
})

View File

@@ -11,21 +11,20 @@
pytest-mockservers,
pytest-resource-path,
pytestCheckHook,
pythonAtLeast,
pytz,
time-machine,
}:
buildPythonPackage (finalAttrs: {
pname = "aioswitcher";
version = "6.3.0";
version = "6.4.0";
pyproject = true;
src = fetchFromGitHub {
owner = "TomerFi";
repo = "aioswitcher";
tag = finalAttrs.version;
hash = "sha256-yxoUUvgImzlANW4XDBaMe/ciBa+JsytoaaKlsq0T6Yc=";
hash = "sha256-VFW2T5VUTraolk93QZMrHx6gRmkPjZzNM2EAcWifasM=";
};
__darwinAllowLocalNetworking = true;
@@ -60,15 +59,6 @@ buildPythonPackage (finalAttrs: {
"test_schedule_parser_with_a_daily_recurring_enabled_schedule_data"
"test_schedule_parser_with_a_partial_daily_recurring_enabled_schedule_data"
"test_schedule_parser_with_a_non_recurring_enabled_schedule_data"
]
++ lib.optionals (pythonAtLeast "3.12") [
# AssertionError: Expected <'I' format requires 0 <= number <= 4294967295> to be equal to <argument out of range>, but was not.
"test_minutes_to_hexadecimal_seconds_with_a_negative_value_should_throw_an_error"
"test_current_timestamp_to_hexadecimal_with_errornous_value_should_throw_an_error"
]
++ lib.optionals (pythonAtLeast "3.14") [
# AssertionError: Expected <hour must be in 0..23, not -1> to be equal
"test_seconds_to_iso_time_with_a_nagative_value_should_throw_an_error"
];
pythonImportsCheck = [ "aioswitcher" ];

View File

@@ -15,22 +15,29 @@
buildPythonPackage (finalAttrs: {
pname = "aiovodafone";
version = "3.3.5";
version = "3.3.11";
pyproject = true;
src = fetchFromGitHub {
owner = "chemelli74";
repo = "aiovodafone";
tag = "v${finalAttrs.version}";
hash = "sha256-AOE4fM+RH3Ls7p2QPdLLq78b5hnxvmqBfib8u/gykfA=";
hash = "sha256-k8DaYuff0rZYVLppVagPphUu/WCoza0IOSp+uoD5oCI=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools>=84.2.1" "setuptools"
'';
# all deps are needlessly pinned to very recent versions
pythonRelaxDeps = true;
build-system = [ setuptools ];
dependencies = [
aiohttp
beautifulsoup4
cryptography
orjson
pycryptodome
segno

View File

@@ -17,14 +17,14 @@
buildPythonPackage (finalAttrs: {
pname = "airgradient";
version = "0.10.0";
version = "0.11.0";
pyproject = true;
src = fetchFromGitHub {
owner = "airgradienthq";
repo = "python-airgradient";
tag = "v${finalAttrs.version}";
hash = "sha256-OlCCImVvoDqOA/LiSShCXwQACHw5Hmwc10BXaMz1DD8=";
hash = "sha256-3W4Uf/PXB6Lk3lOFKB/sU4vDC7OPxU0SbWkFIIEMCYg=";
};
nativeBuildInputs = [ pyprojectVersionPatchHook ];

View File

@@ -7,6 +7,7 @@
pytest-asyncio,
pytest-timeout,
pytestCheckHook,
serialx,
setuptools,
voluptuous,
zigpy,
@@ -14,14 +15,14 @@
buildPythonPackage (finalAttrs: {
pname = "bellows";
version = "1.1.0";
version = "1.2.1";
pyproject = true;
src = fetchFromGitHub {
owner = "zigpy";
repo = "bellows";
tag = finalAttrs.version;
hash = "sha256-Qozk8DraiFcKYtI5bh0/6wa+sbAF3dgnGmP1pIE+9H0=";
hash = "sha256-5Ysj5mHoUdlSapYwW07qqsLH7svYCtUb9tNzHzi/KB8=";
};
postPatch = ''
@@ -35,6 +36,7 @@ buildPythonPackage (finalAttrs: {
dependencies = [
click
click-log
serialx
voluptuous
zigpy
];

View File

@@ -11,14 +11,14 @@
buildPythonPackage rec {
pname = "getmac";
version = "0.9.5";
version = "0.9.6";
pyproject = true;
src = fetchFromGitHub {
owner = "GhostofGoes";
repo = "getmac";
tag = version;
hash = "sha256-ZbTCbbASs7+ChmgcDePXSbiHOst6/eCkq9SiKgYhFyM=";
hash = "sha256-dyuu2P7I4Ce5KJtreTGWYIv0UnSn9b4Y6JfcsBDeD/0=";
};
build-system = [ setuptools ];

View File

@@ -3,29 +3,28 @@
stdenv,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
pytestCheckHook,
uv-build,
}:
buildPythonPackage rec {
pname = "govee-local-api";
version = "3.1.0";
version = "3.3.1";
pyproject = true;
src = fetchFromGitHub {
owner = "Galorhallen";
repo = "govee-local-api";
tag = "v${version}";
hash = "sha256-0MrT99GbtBrYkKxathl51YvaKnyflNQgwnp8JP1zrRc=";
hash = "sha256-JjrO9lOIrkp595+O6usa8wVrKmWyoywHEeIOP5HxL0Q=";
};
postPatch = ''
# dont depend on poetry at runtime
# https://github.com/Galorhallen/govee-local-api/pull/75/files#r1943826599
sed -i '/poetry = "^1.8.5"/d' pyproject.toml
substituteInPlace pyproject.toml \
--replace-fail "uv_build>=0.11.30,<0.12" "uv_build"
'';
build-system = [ poetry-core ];
build-system = [ uv-build ];
nativeCheckInputs = [ pytestCheckHook ];

View File

@@ -31,7 +31,7 @@
buildPythonPackage (finalAttrs: {
pname = "hass-nabucasa";
version = "2.7.0";
version = "2.8.1";
pyproject = true;
disabled = pythonOlder "3.14";
@@ -40,7 +40,7 @@ buildPythonPackage (finalAttrs: {
owner = "nabucasa";
repo = "hass-nabucasa";
tag = finalAttrs.version;
hash = "sha256-neW9v4o0Au9+AYmfzDoGXHOLMvHzQcloinmaZ7O98HY=";
hash = "sha256-awOFbUu2Rh/Fy6BPvUGAt2/+7UodPp0mPwNozWjw9cA=";
};
postPatch = ''

View File

@@ -16,37 +16,38 @@
pytest-vcr,
requests-mock,
setuptools,
websocket-client,
}:
buildPythonPackage rec {
pname = "mastodon-py";
version = "2.2.2";
version = "2.3.3";
pyproject = true;
src = fetchFromGitHub {
owner = "halcy";
repo = "Mastodon.py";
tag = "v${version}";
hash = "sha256-/1oOouJjCCBCymfl9ps3eMDs099cqRY5f4j2jMKKBfE=";
hash = "sha256-c0AHqqb9nBKKccoEPx/jsUm4szGP/CEdBYQbFEAdEF4=";
};
build-system = [ setuptools ];
dependencies = [
blurhash
decorator
python-dateutil
python-magic
requests
];
optional-dependencies = {
blurhash = [ blurhash ];
grapheme = [ graphemeu ];
magic = [ python-magic ];
webpush = [
http-ece
cryptography
];
websocket_streaming = [ websocket-client ];
};
nativeCheckInputs = [

View File

@@ -13,21 +13,27 @@
platformdirs,
typing-extensions,
pytest-asyncio,
pytest-cov-stub,
pytestCheckHook,
}:
buildPythonPackage (finalAttrs: {
pname = "midea-local";
version = "12.2.0";
version = "15.0.0";
pyproject = true;
src = fetchFromGitHub {
owner = "midea-lan";
repo = "midea-local";
tag = "v${finalAttrs.version}";
hash = "sha256-zaEVje2/whWj8PtKNO1WnpKkTdfwG+wor2raNrlAc4w=";
hash = "sha256-I192LNuG2Efxdv4JwN2bLqmSm4E5M0q4ksMwC3t3bvk=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools>=84.2.1" "setuptools"
'';
build-system = [ setuptools ];
dependencies = [
@@ -44,6 +50,7 @@ buildPythonPackage (finalAttrs: {
nativeCheckInputs = [
pytest-asyncio
pytest-cov-stub
pytestCheckHook
];

View File

@@ -15,14 +15,14 @@
buildPythonPackage (finalAttrs: {
pname = "music-assistant-client";
version = "1.5.1";
version = "1.6.0";
pyproject = true;
src = fetchFromGitHub {
owner = "music-assistant";
repo = "client";
tag = "v${finalAttrs.version}";
hash = "sha256-8EsLeRtPH/YZyl8uKyzA1L5n+6lkGAFqYipVbaW4sSg=";
hash = "sha256-BPFx8/G4XfzuOLmssMMhVppmPgKFrdI/R6OKneoToT4=";
};
nativeBuildInputs = [ pyprojectVersionPatchHook ];

View File

@@ -25,14 +25,14 @@ buildPythonPackage (finalAttrs: {
pname = "music-assistant-models";
# Must be compatible with music-assistant-client package
# nixpkgs-update: no auto update
version = "1.1.189";
version = "1.1.214";
pyproject = true;
src = fetchFromGitHub {
owner = "music-assistant";
repo = "models";
tag = finalAttrs.version;
hash = "sha256-oB2ifUUysaJU/nUyTip0C06QujoFSjgowctadIHxDiQ=";
hash = "sha256-Xs0p6ioIFNFOOHSGOWVB7TBa2MY/U6LvJbejD+Z1EF4=";
};
nativeBuildInputs = [ pyprojectVersionPatchHook ];

View File

@@ -16,14 +16,14 @@
buildPythonPackage (finalAttrs: {
pname = "nextdns";
version = "5.1.0";
version = "5.2.0";
pyproject = true;
src = fetchFromGitHub {
owner = "bieniu";
repo = "nextdns";
tag = finalAttrs.version;
hash = "sha256-+ih7QHmtQmWsi6HZZ3xepYBDYlCOyMKo0pQtr6oXpFs=";
hash = "sha256-Z/t2bqiDOfl6QbKAUPUEawNDB9de9hbkzWbDvhTL1T4=";
};
build-system = [ setuptools ];

View File

@@ -1,62 +1,60 @@
{
lib,
aiohttp,
aresponses,
aioresponses,
buildPythonPackage,
fetchFromGitHub,
mashumaro,
orjson,
poetry-core,
pyprojectVersionPatchHook,
pytest-asyncio,
pytest-cov-stub,
pytestCheckHook,
syrupy,
yarl,
}:
buildPythonPackage rec {
buildPythonPackage (finalAttrs: {
pname = "open-meteo";
version = "0.4.0";
version = "1.0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "frenck";
repo = "python-open-meteo";
rev = "v${version}";
hash = "sha256-J106XeSglyqrFfP1ckbnDwfE7IikaNiBQ+m14PE2SBc=";
rev = "v${finalAttrs.version}";
hash = "sha256-rTHHqFiar2W5LTuuXKfUv0tnvjXuNbkfzT80DWXpYiE=";
};
postPatch = ''
# Upstream doesn't set a version for the pyproject.toml
substituteInPlace pyproject.toml \
--replace-fail "0.0.0" "${version}"
'';
nativeBuildInputs = [
pyprojectVersionPatchHook
];
nativeBuildInputs = [ poetry-core ];
build-system = [ poetry-core ];
propagatedBuildInputs = [
dependencies = [
aiohttp
mashumaro
orjson
yarl
];
nativeCheckInputs = [
aresponses
aioresponses
pytest-asyncio
pytest-cov-stub
pytestCheckHook
];
disabledTests = [
# aiohttp api breakage
"test_timeout"
syrupy
];
pythonImportsCheck = [ "open_meteo" ];
meta = {
changelog = "https://github.com/frenck/python-open-meteo/releases/tag/v${version}";
changelog = "https://github.com/frenck/python-open-meteo/releases/tag/${finalAttrs.version}";
description = "Python client for the Open-Meteo API";
homepage = "https://github.com/frenck/python-open-meteo";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ fab ];
};
}
})

View File

@@ -2,7 +2,6 @@
lib,
buildPythonPackage,
fetchFromGitHub,
fetchpatch,
hatchling,
openssl,
pytestCheckHook,
@@ -17,31 +16,18 @@ let
hash = "sha256-SQoNdkWMjnasPjpXQF2yV97MUra8gb27pc3rNoA8Rjw=";
};
in
buildPythonPackage rec {
buildPythonPackage (finalAttrs: {
pname = "paho-mqtt";
version = "2.1.0";
version = "2.2.0";
pyproject = true;
src = fetchFromGitHub {
owner = "eclipse";
repo = "paho.mqtt.python";
rev = "v${version}";
hash = "sha256-VMq+WTW+njK34QUUTE6fR2j2OmHxVzR0wrC92zYb1rY=";
tag = "v${finalAttrs.version}";
hash = "sha256-gYCV8n+pNh62eDitfh4/mj4wu24GEthRtWV5Pa6M9bY=";
};
patches = [
(fetchpatch {
name = "generate-ssl-certs-in-a-test-fixture.patch";
url = "https://github.com/eclipse-paho/paho.mqtt.python/pull/931.diff";
hash = "sha256-A7rWwpR4PnCi77F1VqsQKHBxHNrdeHgmVM6BGMeUpjs=";
})
# backports an upstream fix for flaky tests as repoted here:
# https://github.com/NixOS/nixpkgs/issues/542586
# the fix has already landed in master of paho-mqtt:
# https://github.com/eclipse-paho/paho.mqtt.python/pull/934
./fix-flaky-tests-backport-934.patch
];
build-system = [
hatchling
];
@@ -63,28 +49,13 @@ buildPythonPackage rec {
export PYTHONPATH=".:$PYTHONPATH"
'';
disabledTests = [
# Fails during teardown
# RuntimeError: Client 01-zero-length-clientid.py exited with code None, expected 0
"test_01_zero_length_clientid"
];
disabledTestPaths = [
# Expired key material
# https://github.com/eclipse-paho/paho.mqtt.python/pull/854
"tests/lib/test_08_ssl_connect_alpn.py"
"tests/lib/test_08_ssl_connect_cert_auth.py"
"tests/lib/test_08_ssl_connect_cert_auth_pw.py"
"tests/lib/test_08_ssl_connect_no_auth.py"
];
passthru = {
# bulk updater uses wrong tag
skipBulkUpdate = true;
};
meta = {
changelog = "https://github.com/eclipse/paho.mqtt.python/blob/${src.rev}/ChangeLog.txt";
changelog = "https://github.com/eclipse/paho.mqtt.python/blob/${finalAttrs.src.tag}/ChangeLog.txt";
description = "MQTT version 5.0/3.1.1 client class";
homepage = "https://eclipse.org/paho";
license = lib.licenses.epl20;
@@ -93,4 +64,4 @@ buildPythonPackage rec {
dotlambda
];
};
}
})

View File

@@ -1,184 +0,0 @@
diff --git a/tests/lib/conftest.py b/tests/lib/conftest.py
index 98bbebe..5999085 100644
--- a/tests/lib/conftest.py
+++ b/tests/lib/conftest.py
@@ -2,6 +2,7 @@ import os
import signal
import subprocess
import sys
+import time
import pytest
@@ -45,7 +46,29 @@ def alpn_ssl_server_socket(monkeypatch, ssl_certs_path):
yield from _yield_server(monkeypatch, create_server_socket_ssl(path=ssl_certs_path, alpn_protocols=["paho-test-protocol"]))
-def stop_process(proc: subprocess.Popen) -> None:
+def terminate_process(proc: subprocess.Popen) -> None:
+ proc.terminate()
+ try:
+ # At least on Unix, terminate() isn't an unconditional kill, process
+ # could ignore/handle it.
+ proc.wait(1)
+ except subprocess.TimeoutExpired:
+ # So use kill which is unstoppable on Unix
+ proc.kill()
+ proc.wait(1) # If here we timeout, there is nothing more to do.
+
+
+def stop_process(proc: subprocess.Popen, ready_file) -> None:
+ deadline = time.monotonic() + 5
+ while proc.poll() is None and not ready_file.exists():
+ if time.monotonic() >= deadline:
+ terminate_process(proc)
+ raise RuntimeError("Client did not become ready to stop")
+ time.sleep(0.01)
+
+ if proc.poll() is not None:
+ return
+
if sys.platform == "win32":
proc.send_signal(signal.CTRL_C_EVENT)
else:
@@ -53,17 +76,19 @@ def stop_process(proc: subprocess.Popen) -> None:
try:
proc.wait(5)
except subprocess.TimeoutExpired:
- proc.terminate()
+ terminate_process(proc)
@pytest.fixture()
-def start_client(request: pytest.FixtureRequest, ssl_certs_path):
+def start_client(request: pytest.FixtureRequest, ssl_certs_path, tmp_path):
def starter(name: str, expected_returncode: int = 0) -> None:
client_path = clients_path / name
if not client_path.exists():
raise FileNotFoundError(client_path)
+ ready_file = tmp_path / f"{name}.ready"
env = dict(
os.environ,
+ PAHO_TEST_READY_FILE=str(ready_file),
PAHO_SSL_PATH=str(ssl_certs_path),
PYTHONPATH=f"{tests_path}{os.pathsep}{os.environ.get('PYTHONPATH', '')}",
)
@@ -74,7 +99,7 @@ def start_client(request: pytest.FixtureRequest, ssl_certs_path):
], env=env)
def fin():
- stop_process(proc)
+ stop_process(proc, ready_file)
if proc.returncode != expected_returncode:
raise RuntimeError(f"Client {name} exited with code {proc.returncode}, expected {expected_returncode}")
diff --git a/tests/paho_test.py b/tests/paho_test.py
index 3df996e..188ceef 100644
--- a/tests/paho_test.py
+++ b/tests/paho_test.py
@@ -402,6 +402,11 @@ def pack_remaining_length(remaining_length):
if remaining_length == 0:
return s
+def signal_client_ready():
+ ready_file = os.environ.get("PAHO_TEST_READY_FILE")
+ if ready_file is not None:
+ with open(ready_file, "w"):
+ pass
def loop_until_keyboard_interrupt(mqttc):
"""
@@ -413,6 +418,7 @@ def loop_until_keyboard_interrupt(mqttc):
and stop the client gracefully.
"""
try:
+ signal_client_ready()
while True:
mqttc.loop()
except KeyboardInterrupt:
@@ -431,6 +437,7 @@ def wait_for_keyboard_interrupt():
"""
yield # If we get a KeyboardInterrupt during the block, it's too soon!
try:
+ signal_client_ready()
while True:
time.sleep(0.1)
except KeyboardInterrupt:
diff --git a/tests/test_client.py b/tests/test_client.py
index 09e4606..86652ca 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -864,19 +864,19 @@ class TestCompatibility:
disconnect_packet = paho_test.gen_disconnect()
fake_broker.expect_packet("disconnect", disconnect_packet)
- assert callback_called == [
- "on_connect",
- "on_subscribe",
- "on_publish",
- "on_message",
- "on_unsubscribe",
- "on_disconnect",
- ]
-
finally:
mqttc.disconnect()
mqttc.loop_stop()
+ assert callback_called == [
+ "on_connect",
+ "on_subscribe",
+ "on_publish",
+ "on_message",
+ "on_unsubscribe",
+ "on_disconnect",
+ ]
+
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
@@ -1004,18 +1004,18 @@ class TestCompatibility:
disconnect_packet = paho_test.gen_disconnect()
fake_broker.expect_packet("disconnect", disconnect_packet)
- assert callback_called == [
- "on_connect",
- "on_subscribe",
- "on_publish",
- "on_message",
- "on_unsubscribe",
- "on_disconnect",
- ]
-
finally:
mqttc.disconnect()
mqttc.loop_stop()
+ assert callback_called == [
+ "on_connect",
+ "on_subscribe",
+ "on_publish",
+ "on_message",
+ "on_unsubscribe",
+ "on_disconnect",
+ ]
+
packet_in = fake_broker.receive_packet(1)
assert not packet_in # Check connection is closed
diff --git a/tests/testsupport/broker.py b/tests/testsupport/broker.py
index e08cf73..a587599 100644
--- a/tests/testsupport/broker.py
+++ b/tests/testsupport/broker.py
@@ -59,8 +59,10 @@ class FakeBroker:
if self._conn is None:
raise ValueError('Connection is not open')
- packet_in = self._conn.recv(num_bytes)
- return packet_in
+ try:
+ return self._conn.recv(num_bytes)
+ except ConnectionResetError:
+ return b""
def send_packet(self, packet_out):
if self._conn is None:

View File

@@ -1,25 +1,26 @@
{
lib,
aiohttp,
buildPythonPackage,
fetchFromGitHub,
hatchling,
lib,
lxml,
mocket,
pytest-asyncio,
pytestCheckHook,
yarl,
}:
buildPythonPackage rec {
pname = "pyblu";
version = "2.1.0";
version = "2.2.0";
pyproject = true;
src = fetchFromGitHub {
owner = "LouisChrist";
repo = "pyblu";
tag = "v${version}";
hash = "sha256-5vVdCrvBCLbLlXR2iDtVR6JuJcFYQnuaJMKeor5HvBI=";
hash = "sha256-x9YFXWYUMYLrSNI4afcELdCqETaZggHUnufAXDgrr3I=";
};
pythonRelaxDeps = [ "aiohttp" ];
@@ -29,6 +30,7 @@ buildPythonPackage rec {
dependencies = [
aiohttp
lxml
yarl
];
pythonImportsCheck = [ "pyblu" ];
@@ -43,6 +45,7 @@ buildPythonPackage rec {
# all tests fail with:
# aiohttp.client_exceptions.ClientConnectorDNSError: Cannot connect to host node:11000 ssl:default [Could not contact DNS servers]
"tests/test_player.py"
"tests/test_settings.py"
];
meta = {

View File

@@ -0,0 +1,57 @@
{
lib,
buildPythonPackage,
cryptography,
fetchFromGitHub,
lz4,
pyelftools,
pyprojectVersionPatchHook,
pytestCheckHook,
setuptools,
setuptools-scm,
}:
buildPythonPackage (finalAttrs: {
pname = "pygbl";
version = "1.2.0";
pyproject = true;
src = fetchFromGitHub {
owner = "zigpy";
repo = "pygbl";
tag = "v${finalAttrs.version}";
hash = "sha256-FjtO0J8syPi3KWmumpKrG191mtkFw6dCdlAvRqzuQQI=";
};
build-system = [
setuptools
setuptools-scm
];
nativeBuildInputs = [
pyprojectVersionPatchHook
];
dependencies = [
pyelftools
];
optional-dependencies = {
crypto = [ cryptography ];
lz4 = [ lz4 ];
all =
finalAttrs.passthru.optional-dependencies.crypto ++ finalAttrs.passthru.optional-dependencies.lz4;
};
nativeCheckInputs = [
pytestCheckHook
] ++ finalAttrs.passthru.optional-dependencies.all;
meta = {
changelog = "https://github.com/zigpy/pygbl/releases/tag/${finalAttrs.src.tag}";
description = "Parser for Silicon Labs GBL and EBL firmware images";
homepage = "https://github.com/zigpy/pygbl";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ SuperSandro2000 ];
};
})

View File

@@ -3,6 +3,7 @@
buildPythonPackage,
fetchFromGitHub,
hatchling,
jinja2,
modbus-connection,
pytestCheckHook,
pytest-asyncio,
@@ -11,14 +12,14 @@
buildPythonPackage (finalAttrs: {
pname = "pystiebeleltron";
version = "0.9.2";
version = "0.10.1";
pyproject = true;
src = fetchFromGitHub {
owner = "ThyMYthOS";
repo = "python-stiebel-eltron";
tag = "v${finalAttrs.version}";
hash = "sha256-aSl5JRpp9Mk5bBpXg8SQxDNNTFlkH1HaVT8FLUW8hf8=";
hash = "sha256-9g/ZM3h9ivySAYwDgbswwkIYXeG44IhOvgJyLnwdKps=";
};
build-system = [ hatchling ];
@@ -26,9 +27,10 @@ buildPythonPackage (finalAttrs: {
dependencies = [
modbus-connection
]
++ modbus-connection.optional-dependencies.pymodbus;
++ modbus-connection.optional-dependencies.tmodbus;
nativeCheckInputs = [
jinja2
pytestCheckHook
pytest-asyncio
pytest-mock

View File

@@ -19,14 +19,14 @@
buildPythonPackage (finalAttrs: {
pname = "python-bsblan";
version = "6.1.9";
version = "6.2.1";
pyproject = true;
src = fetchFromGitHub {
owner = "liudger";
repo = "python-bsblan";
tag = "v${finalAttrs.version}";
hash = "sha256-qJm+TNdPkeE+An9VI338i/Wwvb7zCnVRcYG6ooe+kNA=";
hash = "sha256-lNx30Zi4R06sSC27sqal7tWi1Bz9AAAsZhCdjUqlUNQ=";
};
postPatch = ''

View File

@@ -22,14 +22,14 @@
buildPythonPackage (finalAttrs: {
pname = "python-kasa";
version = "0.11.0.1";
version = "0.12.0";
pyproject = true;
src = fetchFromGitHub {
owner = "python-kasa";
repo = "python-kasa";
tag = finalAttrs.version;
hash = "sha256-MrAfYXvLenj5ntJro+vEktZbOB2MnwLQyRGyU+RmYXM=";
hash = "sha256-z984z3Rqh5wZ+Tbum+vOaJjXOL8ljX1g/HkhdlQi4rI=";
};
build-system = [ hatchling ];

View File

@@ -1,30 +1,30 @@
{
lib,
aiohttp,
aiointercept,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
aiohttp,
yarl,
mashumaro,
orjson,
poetry-core,
pyprojectVersionPatchHook,
pytestCheckHook,
pytest-asyncio,
pytest-cov-stub,
aioresponses,
pytestCheckHook,
syrupy,
yarl,
}:
buildPythonPackage rec {
pname = "python-open-router";
version = "0.4.0";
version = "0.5.0";
pyproject = true;
src = fetchFromGitHub {
owner = "joostlek";
repo = "python-open-router";
tag = "v${version}";
hash = "sha256-hf8Ay3/xXH262/1R07mN0iQpOlHFhHb6VUZoYQEq8YI=";
hash = "sha256-Bl+BQePvH4rgGCH4uXS3yVDTGP0XfSId0UdMrfThF0I=";
};
nativeBuildInputs = [ pyprojectVersionPatchHook ];
@@ -33,16 +33,16 @@ buildPythonPackage rec {
dependencies = [
aiohttp
yarl
mashumaro
orjson
yarl
];
nativeCheckInputs = [
pytestCheckHook
aiointercept
pytest-asyncio
pytest-cov-stub
aioresponses
pytestCheckHook
syrupy
];

View File

@@ -14,19 +14,20 @@
buildPythonPackage (finalAttrs: {
pname = "python-openevse-http";
version = "1.5.0";
version = "1.8.0";
pyproject = true;
src = fetchFromGitHub {
owner = "firstof9";
repo = "python-openevse-http";
tag = finalAttrs.version;
hash = "sha256-l4/ZeIi6em5Dmp7O15Wg4brd4J2kTsIxSqLSGFS/Ihs=";
hash = "sha256-5PGRmUP6f7/dis4H1Am//LvIO8OpDCGx773i4H+B3Ls=";
};
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "setuptools-scm>=10.1.1" setuptools_scm
--replace-fail "setuptools>=84.0.0" setuptools \
--replace-fail "setuptools-scm>=10.3.4" setuptools_scm
'';
build-system = [

View File

@@ -7,23 +7,27 @@
pytest-asyncio,
pytest-mock,
pytestCheckHook,
zeroconf,
}:
buildPythonPackage (finalAttrs: {
pname = "python-qube-heatpump";
version = "1.15.0";
version = "1.17.0";
pyproject = true;
src = fetchFromGitHub {
owner = "MattieGit";
repo = "python-qube-heatpump";
tag = "v${finalAttrs.version}";
hash = "sha256-CKILZdoFMIEkRT7KIa8AQaBJXzis/h8Yaf78OF4zjgc=";
hash = "sha256-83eYbL2mS+821f9hDQe/ladPK+ThFawp+Ij7eI8mtng=";
};
build-system = [ hatchling ];
dependencies = [ pymodbus ];
dependencies = [
pymodbus
zeroconf
];
nativeCheckInputs = [
pytest-asyncio

View File

@@ -27,14 +27,14 @@
buildPythonPackage (finalAttrs: {
pname = "samsungtvws";
version = "3.0.6";
version = "3.0.7";
pyproject = true;
src = fetchFromGitHub {
owner = "xchwarze";
repo = "samsung-tv-ws-api";
tag = "v${finalAttrs.version}";
hash = "sha256-2o0CmMhlCx2yVitfwFXXjNQTrDDRlDcDV1kGv/pJxVo=";
hash = "sha256-vME+XCju/4pQTczsxPgs0LJTa4ptWDQlc8jnIKnNMeA=";
};
build-system = [ setuptools ];

View File

@@ -10,14 +10,14 @@
buildPythonPackage rec {
pname = "securetar";
version = "2026.4.1";
version = "2026.10.0";
pyproject = true;
src = fetchFromGitHub {
owner = "home-assistant-libs";
repo = "securetar";
tag = version;
hash = "sha256-y2Ow272094Qrn52LGYkuRcjaR6d0C6bF12g7W6AwSMI=";
hash = "sha256-+XP6bbRbs1ceIq3/juJcwr7NwdYAJg7MM/PZ/FZZZoY=";
};
build-system = [ setuptools ];

View File

@@ -16,14 +16,14 @@
buildPythonPackage (finalAttrs: {
pname = "sense-energy";
version = "0.14.3";
version = "0.15.0";
pyproject = true;
src = fetchFromGitHub {
owner = "scottbonline";
repo = "sense";
tag = finalAttrs.version;
hash = "sha256-Ug58qKlFBe4DpAKMWNup7A2QTslGaaY2OMPyJtnfWfM=";
hash = "sha256-XzOOD40HK/K7H/DvPhCdpLeDv0lDrmLnTiTf+rK4H7Y=";
};
postPatch = ''

View File

@@ -18,14 +18,14 @@
buildPythonPackage (finalAttrs: {
pname = "soco";
version = "0.31.4";
version = "0.32.1";
pyproject = true;
src = fetchFromGitHub {
owner = "SoCo";
repo = "SoCo";
tag = "v${finalAttrs.version}";
hash = "sha256-v24UzJ+/TlEBmNYP51UTI96bvi10E5orNFKS5q1bSyE=";
hash = "sha256-lGHhhZ7zRM06Fnm7yb5gQSWOQUbsBYW3T1/WfQX2PdA=";
};
build-system = [ setuptools ];

View File

@@ -11,14 +11,14 @@
buildPythonPackage (finalAttrs: {
pname = "sofar-modbus";
version = "0.18.0";
version = "0.25.3";
pyproject = true;
src = fetchFromGitHub {
owner = "darkrain-nl";
repo = "sofar-modbus";
tag = finalAttrs.version;
hash = "sha256-Ks8NhghqiXsHwKB+DxZMMFe2ZomVZwpDGX/Avlnf3KE=";
hash = "sha256-yd2ZHxVfxbtduMdgIHaj39juA9nA87G4pdRlLTojev8=";
};
nativeBuildInputs = [

View File

@@ -10,14 +10,14 @@
buildPythonPackage (finalAttrs: {
pname = "tesla-protocol";
version = "3.0.2";
version = "4.0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "Teslemetry";
repo = "tesla-protocol";
tag = "@teslemetry/tesla-protocol@${finalAttrs.version}";
hash = "sha256-kYLSBSxqAd0Gj9ZzYgCZkfN0LGdde/zLqX+3nbHV9+8=";
hash = "sha256-bW3AHgs/Eacml1FBBWUpTkwxFJqvF352o0O4nxxItLc=";
};
sourceRoot = "${finalAttrs.src.name}/packages/python";
@@ -35,6 +35,11 @@ buildPythonPackage (finalAttrs: {
pytestCheckHook
];
disabledTestPaths = [
# testing dependencies isolated is useless and fails
"tests/test_descriptor_namespace.py::DescriptorNamespaceTests"
];
meta = {
changelog = "https://github.com/Teslemetry/tesla-protocol/releases/tag/${finalAttrs.src.tag}";
description = "Tesla vehicle-command, fleet-telemetry and energy protobuf bindings for Python";

View File

@@ -9,30 +9,31 @@
# dependencies
aiohttp,
aiospinel,
bellows,
coloredlogs,
colorlog,
crc,
gpiod,
pygbl,
tqdm,
typing-extensions,
zigpy,
# tests
aioresponses,
pytestCheckHook,
pytest-asyncio,
}:
buildPythonPackage rec {
pname = "universal-silabs-flasher";
version = "1.1.0";
version = "1.3.0";
pyproject = true;
src = fetchFromGitHub {
owner = "NabuCasa";
repo = "universal-silabs-flasher";
tag = "v${version}";
hash = "sha256-niNjHhOwy+5mgs4UY9bIBykmZ+7TifbYnMuG1LAV7PA=";
hash = "sha256-xpeq9W88jp7RM+rzy8T3d/PpuGAeF5RPMgm6EwWc2wI=";
};
postPatch = ''
@@ -45,17 +46,18 @@ buildPythonPackage rec {
dependencies = [
aiohttp
aiospinel
bellows
coloredlogs
colorlog
crc
pygbl
tqdm
typing-extensions
zigpy
]
++ lib.optionals (stdenv.hostPlatform.isLinux) [ gpiod ];
++ lib.optionals stdenv.hostPlatform.isLinux [ gpiod ];
nativeCheckInputs = [
aioresponses
pytestCheckHook
pytest-asyncio
];

View File

@@ -15,14 +15,14 @@
buildPythonPackage (finalAttrs: {
pname = "zeroconf";
version = "0.151.5";
version = "0.153.0";
pyproject = true;
src = fetchFromGitHub {
owner = "jstasiak";
repo = "python-zeroconf";
tag = finalAttrs.version;
hash = "sha256-KDHDVXg1s72iqgPYknp9dHB2oc5jNACdxplxWnPTh6w=";
hash = "sha256-6jxhL1fwzcYt7g6fNqMVNzFZLjfS0cErt4cjS1YQJxU=";
};
build-system = [

View File

@@ -14,7 +14,7 @@
buildPythonPackage rec {
pname = "zha-quirks";
version = "2.3.0";
version = "2.4.1";
pyproject = true;
disabled = pythonOlder "3.12";
@@ -23,7 +23,7 @@ buildPythonPackage rec {
owner = "zigpy";
repo = "zha-device-handlers";
tag = version;
hash = "sha256-F3NUZUepNKef9fJY/eBfbO90ZJXWyzyf5uaZmonaCmc=";
hash = "sha256-lQdiViqRVj10djcq67j1H0l37AA+T/8m8WaFcJwzJVg=";
};
postPatch = ''

View File

@@ -8,7 +8,7 @@
frozendict,
looptime,
pyprojectVersionPatchHook,
pytest-asyncio_0,
pytest-asyncio,
pytest-timeout,
pytest-xdist,
pytestCheckHook,
@@ -26,7 +26,7 @@
buildPythonPackage (finalAttrs: {
pname = "zha";
version = "2.3.1";
version = "2.4.2";
pyproject = true;
disabled = pythonOlder "3.12";
@@ -35,7 +35,7 @@ buildPythonPackage (finalAttrs: {
owner = "zigpy";
repo = "zha";
tag = finalAttrs.version;
hash = "sha256-OwYO22/DEVn6746+KKyUjxCM7C/MdSvPGMfu8/p2y10=";
hash = "sha256-0d3bh1gHCQ4YC4NSi4gKXRzsyTazwY8AC9f/sbbwPrA=";
};
postPatch = ''
@@ -69,7 +69,7 @@ buildPythonPackage (finalAttrs: {
nativeCheckInputs = [
freezegun
looptime
pytest-asyncio_0
pytest-asyncio
pytest-timeout
pytest-xdist
pytestCheckHook

View File

@@ -11,14 +11,14 @@
buildPythonPackage rec {
pname = "zigpy-deconz";
version = "1.0.0";
version = "1.1.1";
pyproject = true;
src = fetchFromGitHub {
owner = "zigpy";
repo = "zigpy-deconz";
tag = version;
hash = "sha256-ZV5X075WEg9FMAphMD9kxnNxJ6TDX7k1EUcDI01mYLw=";
hash = "sha256-xlqxH8j98RyKdSnOhdPKpQMn2z3TbHod9wvq7Lx2OsQ=";
};
postPatch = ''

View File

@@ -5,7 +5,6 @@
setuptools,
aiohttp,
aiospinel,
mashumaro,
pyprojectVersionPatchHook,
pytest-asyncio,
pytestCheckHook,
@@ -14,7 +13,7 @@
buildPythonPackage (finalAttrs: {
pname = "zigpy-ziggurat";
version = "1.1.1";
version = "1.2.0";
pyproject = true;
__structuredAttrs = true;
@@ -22,11 +21,11 @@ buildPythonPackage (finalAttrs: {
owner = "zigpy";
repo = "zigpy-ziggurat";
tag = "v${finalAttrs.version}";
hash = "sha256-Xde97LKGs7Z/qWhjZSNfFowSsExrQiHkp73DqDCGvLQ=";
hash = "sha256-Tf5nAYK/UpqegRFSDCmr0fX40X5BmsLlc+ftggK0Am0=";
};
postPatch = ''
# finds version 0.0.1 instead of 1.0.1
# falls back to wrong version
substituteInPlace pyproject.toml \
--replace-fail ', "setuptools-git-versioning<3"' ""
'';
@@ -42,7 +41,6 @@ buildPythonPackage (finalAttrs: {
dependencies = [
aiohttp
aiospinel
mashumaro
zigpy
];

View File

@@ -27,6 +27,11 @@ buildPythonPackage (finalAttrs: {
hash = "sha256-+rTos8iSyS1b6iAHYbEbStwNH00XQP7SdCwAQBVNnYM=";
};
patches = [
# https://github.com/zigpy/zigpy-znp/pull/291
./zigpy-2.4.1.patch
];
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail "timeout = 20" "timeout = 300" \
@@ -54,12 +59,6 @@ buildPythonPackage (finalAttrs: {
pytestFlags = [ "--reruns=3" ];
disabledTests = [
# broken by https://github.com/zigpy/zigpy/pull/1635
"test_concurrency_auto_config"
"test_request_concurrency"
];
pythonImportsCheck = [ "zigpy_znp" ];
meta = {

View File

@@ -0,0 +1,530 @@
From afe64c762c028df37db3629a8b82933ab221f236 Mon Sep 17 00:00:00 2001
From: puddly <32534428+puddly@users.noreply.github.com>
Date: Wed, 4 Nov 2026 14:33:03 +0000
Subject: [PATCH 1/2] Separate radio TSN from ZCL/ZDO TSN
---
tests/application/test_requests.py | 95 +++++++++++++++++----
tests/conftest.py | 15 ++--
zigpy_znp/zigbee/application.py | 128 ++++++++++++++++-------------
3 files changed, 159 insertions(+), 79 deletions(-)
diff --git a/tests/application/test_requests.py b/tests/application/test_requests.py
index f073cf6..1392a92 100644
--- a/tests/application/test_requests.py
+++ b/tests/application/test_requests.py
@@ -5,6 +5,7 @@
from zigpy.exceptions import DeliveryError
import zigpy.profiles
import zigpy.types as zigpy_t
+import zigpy.zcl.foundation
import zigpy.zdo.types as zdo_t
import zigpy_znp.commands as c
@@ -68,16 +69,15 @@ async def test_zigpy_request(device, make_application):
DstEndpoint=1,
SrcEndpoint=1,
ClusterId=6,
- TSN=TSN,
Data=bytes([0x01, TSN, 0x01]),
partial=True,
),
responses=[
c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS),
- c.AF.DataConfirm.Callback(
+ lambda req: c.AF.DataConfirm.Callback(
Status=t.Status.SUCCESS,
Endpoint=1,
- TSN=TSN,
+ TSN=req.TSN,
),
c.ZDO.SrcRtgInd.Callback(DstAddr=device.nwk, Relays=[]),
c.AF.IncomingMsg.Callback(
@@ -127,16 +127,15 @@ async def test_zigpy_request_failure(device, make_application, mocker):
DstEndpoint=1,
SrcEndpoint=1,
ClusterId=6,
- TSN=TSN,
Data=bytes([0x01, TSN, 0x01]),
partial=True,
),
responses=[
c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS),
- c.AF.DataConfirm.Callback(
+ lambda req: c.AF.DataConfirm.Callback(
Status=t.Status.FAILURE,
Endpoint=1,
- TSN=TSN,
+ TSN=req.TSN,
),
],
)
@@ -251,7 +250,6 @@ async def test_broadcast(device, make_application, mocker):
DstPanId=0x0000,
SrcEndpoint=1,
ClusterId=3,
- TSN=1,
Radius=3,
Data=b"???",
partial=True,
@@ -341,6 +339,72 @@ async def callback(req):
await app.shutdown()
+@pytest.mark.parametrize("device", [FormedLaunchpadCC26X2R1])
+async def test_concurrent_same_tsn_requests(device, make_application):
+ app, znp_server = make_application(server_cls=device)
+ await app.startup(auto_form=False)
+
+ device1 = app.add_initialized_device(ieee=t.EUI64(range(8)), nwk=0xAAAA)
+ device2 = app.add_initialized_device(ieee=t.EUI64(range(1, 9)), nwk=0xBBBB)
+
+ requests = {}
+ both_sent = asyncio.Event()
+
+ def delayed_confirm(req):
+ requests[req.DstAddrModeAddress.address] = req
+
+ if len(requests) == 2:
+ both_sent.set()
+
+ async def inner():
+ await both_sent.wait()
+
+ # The second device fails and its confirm arrives first
+ if req.DstAddrModeAddress.address == device1.nwk:
+ await asyncio.sleep(0.1)
+ status = t.Status.SUCCESS
+ else:
+ status = t.Status.MAC_NO_ACK
+
+ znp_server.send(
+ c.AF.DataConfirm.Callback(Status=status, Endpoint=1, TSN=req.TSN)
+ )
+
+ asyncio.create_task(inner())
+
+ znp_server.reply_to(
+ c.AF.DataRequestExt.Req(partial=True),
+ responses=[
+ c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS),
+ delayed_confirm,
+ ],
+ )
+
+ # Both requests use the same ZCL TSN
+ rsp1, rsp2 = await asyncio.gather(
+ *[
+ app.request(
+ device=dev,
+ profile=260,
+ cluster=1,
+ src_ep=1,
+ dst_ep=1,
+ sequence=1,
+ data=b"\x00\x01\x00",
+ )
+ for dev in (device1, device2)
+ ],
+ return_exceptions=True,
+ )
+
+ assert requests[device1.nwk].TSN != requests[device2.nwk].TSN
+ assert rsp1 == (zigpy.zcl.foundation.Status.SUCCESS, "")
+ assert isinstance(rsp2, DeliveryError)
+ assert rsp2.status == t.Status.MAC_NO_ACK
+
+ await app.shutdown()
+
+
@pytest.mark.parametrize("device", FORMED_DEVICES)
async def test_nonstandard_profile(device, make_application):
app, znp_server = make_application(server_cls=device)
@@ -382,7 +446,7 @@ async def test_nonstandard_profile(device, make_application):
SecurityUse=t.Bool(False),
TimeStamp=12345678,
TSN=0,
- Data=b"\x08" + bytes([req.TSN]) + b"\x0b\x00\x00",
+ Data=b"\x08" + bytes([req.Data[1]]) + b"\x0b\x00\x00",
MacSrcAddr=device.nwk,
MsgResultRadius=29,
),
@@ -554,7 +618,7 @@ def data_confirm_replier(req):
return c.AF.DataConfirm.Callback(
Status=t.Status.SUCCESS if route_discovered else t.Status.NWK_NO_ROUTE,
Endpoint=1,
- TSN=1,
+ TSN=req.TSN,
)
def set_route_discovered(req):
@@ -622,7 +686,7 @@ def data_confirm_replier(req):
return c.AF.DataConfirm.Callback(
Status=next(data_confirm_statuses),
Endpoint=1,
- TSN=1,
+ TSN=req.TSN,
)
znp_server.reply_to(
@@ -707,7 +771,7 @@ def data_confirm_replier(req):
return c.AF.DataConfirm.Callback(
Status=t.Status.MAC_TRANSACTION_EXPIRED if bad_assoc else final_status,
Endpoint=1,
- TSN=1,
+ TSN=req.TSN,
)
znp_server.reply_to(
@@ -871,17 +935,16 @@ async def test_send_security_and_packet_source_route(device, make_application, m
DstEndpoint=packet.dst_ep,
# SrcEndpoint=packet.src_ep,
ClusterId=packet.cluster_id,
- TSN=packet.tsn,
Data=packet.data.serialize(),
SourceRoute=packet.source_route,
partial=True,
),
responses=[
c.AF.DataRequestSrcRtg.Rsp(Status=t.Status.SUCCESS),
- c.AF.DataConfirm.Callback(
+ lambda req: c.AF.DataConfirm.Callback(
Status=t.Status.SUCCESS,
Endpoint=packet.dst_ep,
- TSN=packet.tsn,
+ TSN=req.TSN,
),
],
)
@@ -918,10 +981,10 @@ async def test_send_packet_failure(device, make_application, mocker):
request=c.AF.DataRequestExt.Req(partial=True),
responses=[
c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS),
- c.AF.DataConfirm.Callback(
+ lambda req: c.AF.DataConfirm.Callback(
Status=t.Status.MAC_NO_ACK,
Endpoint=packet.dst_ep,
- TSN=packet.tsn,
+ TSN=req.TSN,
),
],
)
diff --git a/tests/conftest.py b/tests/conftest.py
index 58b2690..d2902c5 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -288,6 +288,7 @@ def zdo_request_matcher(
zdo_kwargs = {k: v for k, v in kwargs.items() if k.startswith("zdo_")}
kwargs = {k: v for k, v in kwargs.items() if not k.startswith("zdo_")}
+ zdo_tsn = kwargs.pop("TSN")
kwargs.setdefault("DstEndpoint", 0x00)
kwargs.setdefault("DstPanId", 0x0000)
kwargs.setdefault("SrcEndpoint", 0x00)
@@ -297,7 +298,7 @@ def zdo_request_matcher(
return c.AF.DataRequestExt.Req(
DstAddrModeAddress=dst_addr,
ClusterId=command_id,
- Data=bytes([kwargs["TSN"]]) + serialize_zdo_command(command_id, **zdo_kwargs),
+ Data=bytes([zdo_tsn]) + serialize_zdo_command(command_id, **zdo_kwargs),
**kwargs,
partial=True,
)
@@ -623,7 +624,7 @@ def on_zdo_mgmt_permit_joining_req(self, req, PermitDuration, TC_Significant):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Mgmt_Permit_Joining_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Mgmt_Permit_Joining_rsp,
@@ -648,7 +649,7 @@ def on_zdo_mgmt_nwk_update_req(self, req, NwkUpdate):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Mgmt_NWK_Update_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Mgmt_NWK_Update_rsp,
@@ -683,7 +684,7 @@ def on_zdo_active_ep_req(self, req, NWKAddrOfInterest):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Active_EP_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Active_EP_rsp,
@@ -743,7 +744,7 @@ def on_zdo_simple_desc_req(self, req, NWKAddrOfInterest, EndPoint):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Simple_Desc_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Simple_Desc_rsp,
@@ -1026,7 +1027,7 @@ def on_zdo_node_desc_req(self, req, NWKAddrOfInterest):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Node_Desc_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Node_Desc_rsp,
@@ -1281,7 +1282,7 @@ def on_zdo_node_desc_req(self, req, NWKAddrOfInterest):
IsBroadcast=t.Bool.false,
ClusterId=zdo_t.ZDOCmd.Node_Desc_rsp,
SecurityUse=0,
- TSN=req.TSN,
+ TSN=req.Data[0],
MacDst=0x0000,
Data=serialize_zdo_command(
command_id=zdo_t.ZDOCmd.Node_Desc_rsp,
diff --git a/zigpy_znp/zigbee/application.py b/zigpy_znp/zigbee/application.py
index 30f33e4..704cd1c 100644
--- a/zigpy_znp/zigbee/application.py
+++ b/zigpy_znp/zigbee/application.py
@@ -57,6 +57,13 @@ def __init__(self, config: conf.ConfigType):
self._version_rsp = None
self._join_announce_tasks: dict[t.EUI64, asyncio.TimerHandle] = {}
+ # Z-Stack only echoes the AF `TransID` back in `AF.DataConfirm`, it must be
+ # unique among in-flight requests. The FIFO delays reuse of recent IDs.
+ self._free_trans_ids: asyncio.Queue[int] = asyncio.Queue()
+
+ for trans_id in range(256):
+ self._free_trans_ids.put_nowait(trans_id)
+
##################################################################
# Implementation of the core zigpy ControllerApplication methods #
##################################################################
@@ -722,31 +729,6 @@ async def _send_request_raw(
# We pick ours based on the registered endpoints when using an older firmware
src_ep = self._find_endpoint(dst_ep=dst_ep, profile=profile, cluster=cluster)
- if relays is None:
- request = c.AF.DataRequestExt.Req(
- DstAddrModeAddress=dst_addr,
- DstEndpoint=dst_ep or 0,
- DstPanId=0x0000,
- SrcEndpoint=src_ep,
- ClusterId=cluster,
- TSN=sequence,
- Options=options,
- Radius=radius,
- Data=data,
- )
- else:
- request = c.AF.DataRequestSrcRtg.Req(
- DstAddr=dst_addr.address,
- DstEndpoint=dst_ep or 0,
- SrcEndpoint=src_ep,
- ClusterId=cluster,
- TSN=sequence,
- Options=options,
- Radius=radius,
- SourceRoute=relays, # force the packet to go through specific parents
- Data=data,
- )
-
if self._znp is None:
raise DeliveryError("Coordinator is disconnected, cannot send request")
@@ -810,39 +792,73 @@ async def _send_request_raw(
)
)
- if dst_ep == ZDO_ENDPOINT or dst_addr.mode == t.AddrMode.Broadcast:
- # Broadcasts and ZDO requests will not receive a confirmation
- await self._znp.request(request=request, RspStatus=t.Status.SUCCESS)
- else:
- async with asyncio.timeout(
- EXTENDED_DATA_CONFIRM_TIMEOUT
- if extended_timeout
- else DATA_CONFIRM_TIMEOUT
- ):
- # Shield from cancellation to prevent requests that time out in higher
- # layers from missing expected responses
- response = await asyncio.shield(
- self._znp.request_callback_rsp(
- request=request,
- RspStatus=t.Status.SUCCESS,
- callback=c.AF.DataConfirm.Callback(
- partial=True,
- TSN=sequence,
- # XXX: can this ever not match?
- # Endpoint=src_ep,
- ),
- # Multicasts eventually receive a confirmation but waiting for
- # it is unnecessary
- background=(dst_addr.mode == t.AddrMode.Group),
- )
+ trans_id = await self._free_trans_ids.get()
+ confirm_task = None
+
+ try:
+ if relays is None:
+ request = c.AF.DataRequestExt.Req(
+ DstAddrModeAddress=dst_addr,
+ DstEndpoint=dst_ep or 0,
+ DstPanId=0x0000,
+ SrcEndpoint=src_ep,
+ ClusterId=cluster,
+ TSN=trans_id,
+ Options=options,
+ Radius=radius,
+ Data=data,
+ )
+ else:
+ request = c.AF.DataRequestSrcRtg.Req(
+ DstAddr=dst_addr.address,
+ DstEndpoint=dst_ep or 0,
+ SrcEndpoint=src_ep,
+ ClusterId=cluster,
+ TSN=trans_id,
+ Options=options,
+ Radius=radius,
+ SourceRoute=relays, # force the packet through specific parents
+ Data=data,
)
- # Both the callback and the response can have an error status
- if response.Status != t.Status.SUCCESS:
- raise InvalidCommandResponse(
- f"Unsuccessful request status code: {response.Status!r}",
- response,
- )
+ if dst_ep == ZDO_ENDPOINT or dst_addr.mode == t.AddrMode.Broadcast:
+ # Broadcasts and ZDO requests will not receive a confirmation
+ await self._znp.request(request=request, RspStatus=t.Status.SUCCESS)
+ return
+
+ confirm_task = asyncio.create_task(
+ self._znp.request_callback_rsp(
+ request=request,
+ RspStatus=t.Status.SUCCESS,
+ callback=c.AF.DataConfirm.Callback(partial=True, TSN=trans_id),
+ # Multicasts eventually receive a confirmation but waiting for
+ # it is unnecessary
+ background=(dst_addr.mode == t.AddrMode.Group),
+ )
+ )
+ finally:
+ if confirm_task is None:
+ self._free_trans_ids.put_nowait(trans_id)
+ else:
+ # The confirm listener can outlive this coroutine, keep the ID until
+ # it is gone
+ confirm_task.add_done_callback(
+ lambda _: self._free_trans_ids.put_nowait(trans_id)
+ )
+
+ async with asyncio.timeout(
+ EXTENDED_DATA_CONFIRM_TIMEOUT if extended_timeout else DATA_CONFIRM_TIMEOUT
+ ):
+ # Shield from cancellation to prevent requests that time out in higher
+ # layers from missing expected responses
+ response = await asyncio.shield(confirm_task)
+
+ # Both the callback and the response can have an error status
+ if response.Status != t.Status.SUCCESS:
+ raise InvalidCommandResponse(
+ f"Unsuccessful request status code: {response.Status!r}",
+ response,
+ )
@combine_concurrent_calls
async def _discover_route(self, nwk: t.NWK) -> None:
From 2e2b8ef461c3a37df0fd0da7c742b0219fb1694f Mon Sep 17 00:00:00 2001
From: puddly <32534428+puddly@users.noreply.github.com>
Date: Wed, 4 Nov 2026 15:48:34 +0000
Subject: [PATCH 2/2] Bump minimum zigpy version
---
pyproject.toml | 2 +-
tests/application/test_joining.py | 3 +++
tests/application/test_startup.py | 5 +++--
tests/conftest.py | 12 ++++++++++++
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index d3153d2..f64d622 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,7 +14,7 @@ readme = "README.md"
license = {text = "GPL-3.0"}
requires-python = ">=3.11"
dependencies = [
- "zigpy>=1.5.0",
+ "zigpy>=2.4.1",
"voluptuous",
"coloredlogs",
"jsonschema",
diff --git a/tests/application/test_joining.py b/tests/application/test_joining.py
index 886a92d..c4abc0b 100644
--- a/tests/application/test_joining.py
+++ b/tests/application/test_joining.py
@@ -60,6 +60,9 @@ async def test_permit_join(device, mocker, make_application):
)
await app.startup(auto_form=False)
+
+ # Green Power commissioning also consumes sequence numbers
+ mocker.patch.object(app, "get_sequence", return_value=2)
await app.permit(time_s=10)
await permit_join_broadcast
diff --git a/tests/application/test_startup.py b/tests/application/test_startup.py
index 8211bc9..fda0925 100644
--- a/tests/application/test_startup.py
+++ b/tests/application/test_startup.py
@@ -103,10 +103,11 @@ async def test_endpoints(device, make_application):
await app.startup(auto_form=False)
- # We currently just register two endpoints
- assert len(endpoints) == 2
+ # ZHA, ZLL, and Green Power
+ assert len(endpoints) == 3
assert 1 in app._device.endpoints
assert 2 in app._device.endpoints
+ assert 242 in app._device.endpoints
await app.shutdown()
diff --git a/tests/conftest.py b/tests/conftest.py
index d2902c5..e6566a1 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -17,7 +17,9 @@
from asynctest import CoroutineMock # type:ignore[no-redef] # noqa: F401
import zigpy.endpoint
+from zigpy.zcl.clusters.greenpower import GreenPowerProxy
import zigpy.zdo.types as zdo_t
+import zigpy.zgp
from zigpy_znp.api import ZNP
import zigpy_znp.commands as c
@@ -595,6 +597,16 @@ def permit_join(self, request):
c.ZDO.MgmtPermitJoinRsp.Callback(Src=0x0000, Status=t.ZDOStatus.SUCCESS),
]
+ @reply_to(
+ c.AF.DataRequestExt.Req(
+ partial=True,
+ DstEndpoint=zigpy.zgp.GP_ENDPOINT,
+ ClusterId=GreenPowerProxy.cluster_id,
+ )
+ )
+ def on_gp_broadcast(self, req):
+ return [c.AF.DataRequestExt.Rsp(Status=t.Status.SUCCESS)]
+
@reply_to(c.AF.DataRequestExt.Req(partial=True, DstEndpoint=0))
def on_zdo_request(self, req):
kwargs = deserialize_zdo_command(req.ClusterId, req.Data[1:])

View File

@@ -24,14 +24,14 @@
buildPythonPackage (finalAttrs: {
pname = "zigpy";
version = "2.3.0";
version = "2.4.1";
pyproject = true;
src = fetchFromGitHub {
owner = "zigpy";
repo = "zigpy";
tag = finalAttrs.version;
hash = "sha256-zDwd++phuXhK5wkwV2m23KF3tu3h/n8eKjkkPZH1oDQ=";
hash = "sha256-B0qqlnQPLJ91clfUuOeLrY8dAij1cojezQnV7J483zQ=";
};
postPatch = ''

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
lib,
callPackage,
coreutils,
unzip,
fetchFromGitHub,
fetchPypi,
python314Packages,
@@ -122,10 +123,12 @@ let
# internal python packages only consumed by home-assistant itself
gazetteer-matcher = self.callPackage ./python-modules/gazetteer-matcher { };
hassfest = self.callPackage ./python-modules/hassfest { };
hass-web-proxy-lib = self.callPackage ./python-modules/hass-web-proxy-lib { };
home-assistant-frontend = self.callPackage ./frontend.nix { };
home-assistant-intents = self.callPackage ./intents.nix { };
homeassistant = self.toPythonModule home-assistant;
pytest-homeassistant = self.callPackage ./python-modules/pytest-homeassistant { };
pytest-homeassistant-custom-component =
self.callPackage ./pytest-homeassistant-custom-component.nix
{ };
@@ -152,7 +155,7 @@ let
extraBuildInputs = extraPackages python3Packages;
# Don't forget to run update-component-packages.py after updating
hassVersion = "2026.10.4";
hassVersion = "2026.11.0";
in
python3Packages.buildPythonApplication rec {
@@ -173,28 +176,38 @@ python3Packages.buildPythonApplication rec {
owner = "home-assistant";
repo = "core";
tag = version;
hash = "sha256-RMjpLX8zFslvCkR6jYeinBpbKKYdiC+gdff90S4Dz4w=";
hash = "sha256-NYGt64VZiAZSVViO6pgjx7fBk9YgIDMDmKLNSFVsw6Q=";
};
# Secondary source is pypi sdist for translations
sdist = fetchPypi {
# Secondary source is pypi wheel for translations
wheel = fetchPypi {
inherit pname version;
hash = "sha256-hBD+y0NKuUs/dyTNgFhAUPDO64VsFu5wICwkA31iI4o=";
hash = "sha256-fKX73p3qh5rHcjlJ/IQ0eqxRguYwnDV7Lklz/TkbAPc=";
format = "wheel";
dist = "py3";
python = "py3";
};
nativeBuildInputs = [
unzip
];
build-system = with python3Packages; [
setuptools
];
pythonRelaxDeps = true;
# extract translations from pypi sdist
# extract translations from wheel
prePatch = ''
tar --extract --gzip --file $sdist --strip-components 1 --wildcards "**/translations"
unzip "$wheel" '**/translations/*' -d .
'';
# leave this in, so users don't have to constantly update their downstream patch handling
patches = [
# Skip environment check
./patches/skip-environment-check.patch
# Follow symlinks in /var/lib/hass/www
./patches/static-follow-symlinks.patch
@@ -260,7 +273,7 @@ python3Packages.buildPythonApplication rec {
hass-nabucasa
home-assistant-bluetooth
home-assistant-intents
httpx
httpx2
ifaddr
infrared-protocols
jinja2
@@ -275,6 +288,7 @@ python3Packages.buildPythonApplication rec {
pyjwt
pymicro-vad
pyopenssl
pyserial
pyspeex-noise
python-slugify
pyturbojpeg
@@ -285,6 +299,7 @@ python3Packages.buildPythonApplication rec {
sqlalchemy
standard-aifc
standard-telnetlib
truststore
typing-extensions
ulid-transform
urllib3
@@ -306,10 +321,13 @@ python3Packages.buildPythonApplication rec {
requirementsTest = with python3Packages; [
# test infrastructure (selectively from requirement_test.txt)
hassfest
pytest-homeassistant
freezegun
pytest-asyncio
pytest-aiohttp
pytest-freezer
pytest-homeassistant
pytest-socket
pytest-timeout
pytest-unordered
@@ -357,10 +375,9 @@ python3Packages.buildPythonApplication rec {
];
disabledTestPaths = [
# we neither run nor distribute hassfest
"tests/hassfest"
# we don't care about code quality
"tests/pylint"
"tests/script"
# redundant component import test, which would make debugpy & sentry expensive to review
"tests/test_circular_imports.py"
# don't bulk test all components

View File

@@ -8,7 +8,7 @@ buildPythonPackage (finalAttrs: {
# the frontend version corresponding to a specific home-assistant version can be found here
# https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/frontend/manifest.json
pname = "home-assistant-frontend";
version = "20260930.5";
version = "20261028.4";
format = "wheel";
src = fetchPypi {
@@ -17,7 +17,7 @@ buildPythonPackage (finalAttrs: {
pname = "home_assistant_frontend";
dist = "py3";
python = "py3";
hash = "sha256-nMA7PSpD6TxuV8wgsyLJjM5hvno118HfECHiedItH5s=";
hash = "sha256-5eWbguY7KIMj01iGJy8uSQ7mL2x6qixW5+9F4wDUR1c=";
};
# there is nothing to strip in this package

View File

@@ -0,0 +1,18 @@
diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py
index 8a7772fcc27..ea8bb79536d 100644
--- a/homeassistant/__main__.py
+++ b/homeassistant/__main__.py
@@ -16,13 +16,6 @@ FAULT_LOG_FILENAME = "home-assistant.log.fault"
def validate_environment() -> None:
"""Validate that Home Assistant is started from a container or a venv."""
- if not is_virtual_env() and not is_docker_env():
- print(
- "Home Assistant must be run in a Python virtual environment or a container.",
- file=sys.stderr,
- )
- sys.exit(1)
-
def validate_os() -> None:
"""Validate that Home Assistant is running in a supported operating system."""

View File

@@ -0,0 +1,33 @@
{
buildPythonPackage,
home-assistant,
# build-system
setuptools,
# tests
pytestCheckHook,
ruff,
}:
buildPythonPackage {
pname = "hassfest";
pyproject = true;
inherit (home-assistant) version src;
sourceRoot = "${home-assistant.src.name}/packages/hassfest";
build-system = [ setuptools ];
pythonImportsCheck = [ "hassfest" ];
nativeCheckInputs = [
pytestCheckHook
ruff
];
meta = home-assistant.meta // {
description = "Validate Home Asisstant integrations";
};
}

View File

@@ -0,0 +1,90 @@
{
buildPythonPackage,
home-assistant,
pyprojectVersionPatchHook,
# build-system
setuptools,
# dependencies
bleak-retry-connector,
freezegun,
paho-mqtt,
pytest,
pytest-aiohttp,
pytest-asyncio,
pytest-freezer,
pytest-socket,
pytest-xdist,
requests-mock,
respx,
syrupy,
# optional-dependencies
aiohasupervisor,
aiousbwatcher,
bluetooth-adapters,
bluetooth-auto-recovery,
bluetooth-data-tools,
habluetooth,
serialx,
infrared-protocols,
rf-protocols,
}:
buildPythonPackage {
pname = "pytest-homeassistant";
pyproject = true;
inherit (home-assistant) version src;
sourceRoot = "${home-assistant.src.name}/packages/pytest-homeassistant";
nativeBuildInputs = [ pyprojectVersionPatchHook ];
build-system = [ setuptools ];
dependencies = [
bleak-retry-connector
freezegun
paho-mqtt
pytest
pytest-aiohttp
pytest-asyncio
pytest-freezer
pytest-socket
pytest-xdist
requests-mock
respx
syrupy
];
pythonRelaxDeps = [
"pytest"
"syrupy"
];
pythonRemoveDeps = [ "homeassistant" ]; # circular
optional-dependencies = {
bluetooth = [
aiohasupervisor
aiousbwatcher
bluetooth-adapters
bluetooth-auto-recovery
bluetooth-data-tools
habluetooth
serialx
];
infrared = [
infrared-protocols
];
radio-frequency = [
rf-protocols
];
};
meta = home-assistant.meta // {
description = "Pytest fixtures and test helpers for Home Assistant";
};
}

View File

@@ -71,6 +71,7 @@ let
mobile_app = getComponentDeps "frontend";
mopeka = getComponentDeps "switchbot";
mqtt = getComponentDeps "homeassistant_hardware";
music_assistant = getComponentDeps "homeassistant_hardware";
nest = [
av
];

View File

@@ -111,7 +111,7 @@ def parse_components(version: str = "master"):
components_with_tests.append(entry.name)
sys.path.append(core_path)
from script.hassfest.model import Config, Integration # type: ignore
from packages.hassfest.hassfest.model import Config, Integration # type: ignore
config = Config(
root=pathlib.Path(core_path),
@@ -346,5 +346,4 @@ def main() -> None:
if __name__ == "__main__":
run_sync(["pyright", __file__])
run_sync(["ruff", "check", "--ignore=E501,EXE", __file__])
run_sync(["isort", __file__])
main()

View File

@@ -189,9 +189,21 @@ class HomeAssistant:
async def update_core(self, old_version: str, new_version: str) -> None:
old_sdist_hash = str(await Nix.eval("home-assistant.sdist.outputHash"))
new_sdist_hash = await Nurl.prefetch("https://pypi.org/project/homeassistant/", new_version)
print(f"sdist: {old_sdist_hash} -> {new_sdist_hash}")
old_wheel_hash = str(await Nix.eval("home-assistant.wheel.outputHash"))
new_wheel_hash = await Nurl.prefetch(
"https://pypi.org/project/homeassistant/",
new_version,
"--arg-str",
"format",
"wheel",
"--arg-str",
"dist",
"py3",
"--arg-str",
"python",
"py3",
)
print(f"wheel: {old_wheel_hash} -> {new_wheel_hash}")
old_git_hash = str(await Nix.eval("home-assistant.src.outputHash"))
new_git_hash = await Nurl.prefetch("https://github.com/home-assistant/core/", new_version)
@@ -207,9 +219,15 @@ class HomeAssistant:
new_hash = await Nurl.prefetch(
"https://pypi.org/project/home_assistant_frontend/",
new_version,
"-A", "format", "wheel",
"-A", "dist", "py3",
"-A", "python", "py3"
"--arg-str",
"format",
"wheel",
"--arg-str",
"dist",
"py3",
"--arg-str",
"python",
"py3",
)
print(f"frontend: {old_hash} -> {new_hash}")

View File

@@ -15212,6 +15212,8 @@ self: super: with self; {
pygatt = callPackage ../development/python-modules/pygatt { };
pygbl = callPackage ../development/python-modules/pygbl { };
pygccxml = callPackage ../development/python-modules/pygccxml { };
pygdbmi = callPackage ../development/python-modules/pygdbmi { };