mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-11-05 20:30:18 +00:00
Compare commits
54 Commits
master
...
wip-home-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64b0db6e10 | ||
|
|
6f3c9b219e | ||
|
|
c0d1285f41 | ||
|
|
85d82c7a0b | ||
|
|
b0a03543a8 | ||
|
|
6a0bf99af5 | ||
|
|
9a5db4ef77 | ||
|
|
f19359bb9b | ||
|
|
864ccdc6d9 | ||
|
|
283f7cece0 | ||
|
|
7f6ab4f8b6 | ||
|
|
e0abd133ad | ||
|
|
e8157e600c | ||
|
|
ac729f3bad | ||
|
|
526d05ebd6 | ||
|
|
76f2f572fe | ||
|
|
e5fcd544bf | ||
|
|
fc388689aa | ||
|
|
747a955030 | ||
|
|
8d1df0105c | ||
|
|
baccdab2c2 | ||
|
|
e4d1530f1c | ||
|
|
03ea925282 | ||
|
|
a04dd970dc | ||
|
|
15c56829d3 | ||
|
|
0f01130789 | ||
|
|
72152964c4 | ||
|
|
5eea90ff0b | ||
|
|
9fdd8f7e0e | ||
|
|
a6c56e5362 | ||
|
|
1634d8d9d2 | ||
|
|
f49a1ca855 | ||
|
|
bc1e022af2 | ||
|
|
911197569e | ||
|
|
cdf76905ce | ||
|
|
a5a8f40628 | ||
|
|
8df6f8dd87 | ||
|
|
873bf1e8d6 | ||
|
|
bb62ba29b9 | ||
|
|
e79c2ec8df | ||
|
|
5ca2a69844 | ||
|
|
6457f3a943 | ||
|
|
77ff7866a8 | ||
|
|
00b3cb7239 | ||
|
|
a4205f5922 | ||
|
|
1380c33506 | ||
|
|
25f411ca5a | ||
|
|
f239ff4bff | ||
|
|
6a38ccab79 | ||
|
|
5adf66627a | ||
|
|
a3f1a4bec9 | ||
|
|
75303e4989 | ||
|
|
f560255820 | ||
|
|
c3153ea069 |
@@ -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" ];
|
||||
|
||||
40
pkgs/development/python-modules/adguardhome/typer-0.26.patch
Normal file
40
pkgs/development/python-modules/adguardhome/typer-0.26.patch
Normal 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)
|
||||
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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" ];
|
||||
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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 = [ ];
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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" ];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
];
|
||||
};
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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:
|
||||
@@ -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 = {
|
||||
|
||||
57
pkgs/development/python-modules/pygbl/default.nix
Normal file
57
pkgs/development/python-modules/pygbl/default.nix
Normal 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 ];
|
||||
};
|
||||
})
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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 ];
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
530
pkgs/development/python-modules/zigpy-znp/zigpy-2.4.1.patch
Normal file
530
pkgs/development/python-modules/zigpy-znp/zigpy-2.4.1.patch
Normal 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:])
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."""
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
@@ -71,6 +71,7 @@ let
|
||||
mobile_app = getComponentDeps "frontend";
|
||||
mopeka = getComponentDeps "switchbot";
|
||||
mqtt = getComponentDeps "homeassistant_hardware";
|
||||
music_assistant = getComponentDeps "homeassistant_hardware";
|
||||
nest = [
|
||||
av
|
||||
];
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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 { };
|
||||
|
||||
Reference in New Issue
Block a user