PyPlumIO 0.5.16__tar.gz → 0.5.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.pre-commit-config.yaml +2 -2
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PKG-INFO +10 -10
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/PKG-INFO +10 -10
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/requires.txt +9 -9
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/schedules.rst +3 -3
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/_version.py +2 -2
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/__init__.py +2 -2
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/ecomax.py +2 -2
- pyplumio-0.5.18/pyplumio/helpers/factory.py +28 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/parameter.py +5 -6
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/schedule.py +7 -8
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/protocol.py +11 -8
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/stream.py +2 -2
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/ecomax_parameters.py +27 -38
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/mixer_parameters.py +17 -16
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/schedules.py +11 -10
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/thermostat_parameters.py +20 -19
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyproject.toml +9 -9
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/requirements_docs.txt +1 -1
- pyplumio-0.5.18/requirements_test.txt +11 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_factory.py +7 -7
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_parameter.py +4 -5
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_schedule.py +4 -4
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_devices.py +26 -13
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_protocol.py +1 -1
- PyPlumIO-0.5.16/pyplumio/helpers/factory.py +0 -20
- PyPlumIO-0.5.16/requirements_test.txt +0 -11
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.gitattributes +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/CODE_OF_CONDUCT.md +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/dependabot.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/ci.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/codeql-analysis.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/deploy.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.github/workflows/documentation.yml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.gitignore +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/.vscode/settings.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/LICENSE +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/MANIFEST.in +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/PyPlumIO.egg-info/top_level.txt +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/README.md +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/Makefile +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/make.bat +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/callbacks.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/conf.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/connecting.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/index.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/mixers_thermostats.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/protocol.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/reading.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/docs/source/writing.rst +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/images/ecomax.png +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/images/rs485.png +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/__main__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/connection.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/const.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/ecoster.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/mixer.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/devices/thermostat.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/exceptions.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/filters.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/messages.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/requests.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/frames/responses.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/data_types.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/event_manager.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/task_manager.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/timeout.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/typing.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/helpers/uid.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/py.typed +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/alerts.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/boiler_load.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/boiler_power.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fan_power.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/frame_versions.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fuel_consumption.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/fuel_level.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/lambda_sensor.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/mixer_sensors.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/modules.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/network_info.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/output_flags.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/outputs.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/pending_alerts.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/product_info.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/program_version.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/regulator_data.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/regulator_data_schema.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/statuses.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/temperatures.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/structures/thermostat_sensors.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/pyplumio/utils.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/requirements.txt +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/setup.cfg +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/conftest.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_init.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_messages.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_requests.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/frames/test_responses.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/__init__.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_data_types.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_event_manager.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_task_manager.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_timeout.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/helpers/test_uid.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/ruff.toml +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_connection.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_filters.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_init.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_main.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_stream.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/test_utils.py +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/messages/regulator_data.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/messages/sensor_data.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/alerts.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/ecomax_control.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/mixer_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_schedule.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/alerts.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/device_available.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/mixer_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/password.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/program_version.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/schedules.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/responses/uid.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {PyPlumIO-0.5.16 → pyplumio-0.5.18}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -2,7 +2,7 @@
|
|
2
2
|
# See https://pre-commit.com/hooks.html for more hooks
|
3
3
|
repos:
|
4
4
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
5
|
-
rev: v0.
|
5
|
+
rev: v0.4.2
|
6
6
|
hooks:
|
7
7
|
- id: ruff
|
8
8
|
args:
|
@@ -12,6 +12,6 @@ repos:
|
|
12
12
|
hooks:
|
13
13
|
- id: codespell
|
14
14
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
15
|
-
rev: v1.
|
15
|
+
rev: v1.10.0
|
16
16
|
hooks:
|
17
17
|
- id: mypy
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: PyPlumIO
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.18
|
4
4
|
Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
5
5
|
Author-email: Denis Paavilainen <denpa@denpa.pro>
|
6
6
|
License: MIT License
|
@@ -25,21 +25,21 @@ License-File: LICENSE
|
|
25
25
|
Requires-Dist: pyserial-asyncio==0.6
|
26
26
|
Provides-Extra: test
|
27
27
|
Requires-Dist: codespell==2.2.6; extra == "test"
|
28
|
-
Requires-Dist: coverage==7.
|
29
|
-
Requires-Dist: mypy==1.
|
28
|
+
Requires-Dist: coverage==7.5.1; extra == "test"
|
29
|
+
Requires-Dist: mypy==1.10.0; extra == "test"
|
30
30
|
Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
|
31
|
-
Requires-Dist: pytest==8.
|
32
|
-
Requires-Dist: pytest-asyncio==0.23.
|
33
|
-
Requires-Dist: ruff==0.3
|
34
|
-
Requires-Dist: tox==4.
|
35
|
-
Requires-Dist: types-pyserial==3.5.0.
|
31
|
+
Requires-Dist: pytest==8.2.0; extra == "test"
|
32
|
+
Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
|
33
|
+
Requires-Dist: ruff==0.4.3; extra == "test"
|
34
|
+
Requires-Dist: tox==4.15.0; extra == "test"
|
35
|
+
Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
|
36
36
|
Provides-Extra: docs
|
37
|
-
Requires-Dist: sphinx==7.
|
37
|
+
Requires-Dist: sphinx==7.3.7; extra == "docs"
|
38
38
|
Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
|
39
39
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
40
40
|
Provides-Extra: dev
|
41
41
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
42
|
-
Requires-Dist: pre-commit==3.
|
42
|
+
Requires-Dist: pre-commit==3.7.0; extra == "dev"
|
43
43
|
Requires-Dist: tomli==2.0.1; extra == "dev"
|
44
44
|
|
45
45
|
# PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: PyPlumIO
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.18
|
4
4
|
Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
5
5
|
Author-email: Denis Paavilainen <denpa@denpa.pro>
|
6
6
|
License: MIT License
|
@@ -25,21 +25,21 @@ License-File: LICENSE
|
|
25
25
|
Requires-Dist: pyserial-asyncio==0.6
|
26
26
|
Provides-Extra: test
|
27
27
|
Requires-Dist: codespell==2.2.6; extra == "test"
|
28
|
-
Requires-Dist: coverage==7.
|
29
|
-
Requires-Dist: mypy==1.
|
28
|
+
Requires-Dist: coverage==7.5.1; extra == "test"
|
29
|
+
Requires-Dist: mypy==1.10.0; extra == "test"
|
30
30
|
Requires-Dist: pyserial-asyncio-fast==0.11; extra == "test"
|
31
|
-
Requires-Dist: pytest==8.
|
32
|
-
Requires-Dist: pytest-asyncio==0.23.
|
33
|
-
Requires-Dist: ruff==0.3
|
34
|
-
Requires-Dist: tox==4.
|
35
|
-
Requires-Dist: types-pyserial==3.5.0.
|
31
|
+
Requires-Dist: pytest==8.2.0; extra == "test"
|
32
|
+
Requires-Dist: pytest-asyncio==0.23.6; extra == "test"
|
33
|
+
Requires-Dist: ruff==0.4.3; extra == "test"
|
34
|
+
Requires-Dist: tox==4.15.0; extra == "test"
|
35
|
+
Requires-Dist: types-pyserial==3.5.0.20240311; extra == "test"
|
36
36
|
Provides-Extra: docs
|
37
|
-
Requires-Dist: sphinx==7.
|
37
|
+
Requires-Dist: sphinx==7.3.7; extra == "docs"
|
38
38
|
Requires-Dist: sphinx_rtd_theme==2.0.0; extra == "docs"
|
39
39
|
Requires-Dist: readthedocs-sphinx-search==0.3.2; extra == "docs"
|
40
40
|
Provides-Extra: dev
|
41
41
|
Requires-Dist: pyplumio[docs,test]; extra == "dev"
|
42
|
-
Requires-Dist: pre-commit==3.
|
42
|
+
Requires-Dist: pre-commit==3.7.0; extra == "dev"
|
43
43
|
Requires-Dist: tomli==2.0.1; extra == "dev"
|
44
44
|
|
45
45
|
# PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
|
@@ -2,21 +2,21 @@ pyserial-asyncio==0.6
|
|
2
2
|
|
3
3
|
[dev]
|
4
4
|
pyplumio[docs,test]
|
5
|
-
pre-commit==3.
|
5
|
+
pre-commit==3.7.0
|
6
6
|
tomli==2.0.1
|
7
7
|
|
8
8
|
[docs]
|
9
|
-
sphinx==7.
|
9
|
+
sphinx==7.3.7
|
10
10
|
sphinx_rtd_theme==2.0.0
|
11
11
|
readthedocs-sphinx-search==0.3.2
|
12
12
|
|
13
13
|
[test]
|
14
14
|
codespell==2.2.6
|
15
|
-
coverage==7.
|
16
|
-
mypy==1.
|
15
|
+
coverage==7.5.1
|
16
|
+
mypy==1.10.0
|
17
17
|
pyserial-asyncio-fast==0.11
|
18
|
-
pytest==8.
|
19
|
-
pytest-asyncio==0.23.
|
20
|
-
ruff==0.3
|
21
|
-
tox==4.
|
22
|
-
types-pyserial==3.5.0.
|
18
|
+
pytest==8.2.0
|
19
|
+
pytest-asyncio==0.23.6
|
20
|
+
ruff==0.4.3
|
21
|
+
tox==4.15.0
|
22
|
+
types-pyserial==3.5.0.20240311
|
@@ -55,7 +55,7 @@ switches back to daytime mode from 07:00 to 00:00.
|
|
55
55
|
heating_schedule = schedules["heating"]
|
56
56
|
heating_schedule.monday.set_off(start="00:00", end="07:00")
|
57
57
|
heating_schedule.monday.set_on(start="07:00", end="00:00")
|
58
|
-
heating_schedule.commit()
|
58
|
+
await heating_schedule.commit()
|
59
59
|
|
60
60
|
For clarity sake, you might want to use ``STATE_NIGHT`` and
|
61
61
|
``STATE_DAY`` constants from ``pyplumio.helpers.schedule`` module.
|
@@ -99,7 +99,7 @@ Schedule object:
|
|
99
99
|
weekday.set_off("07:00", "00:00")
|
100
100
|
|
101
101
|
# Commit changes to the device.
|
102
|
-
heating_schedule.commit()
|
102
|
+
await heating_schedule.commit()
|
103
103
|
|
104
104
|
Schedule Examples
|
105
105
|
-----------------
|
@@ -131,7 +131,7 @@ Schedule Examples
|
|
131
131
|
# There will be no nighttime mode on sunday.
|
132
132
|
heating_schedule.sunday.set_state(STATE_DAY)
|
133
133
|
|
134
|
-
heating_schedule.commit()
|
134
|
+
await heating_schedule.commit()
|
135
135
|
|
136
136
|
|
137
137
|
asyncio.run(main())
|
@@ -11,7 +11,7 @@ from pyplumio.const import ATTR_FRAME_ERRORS, ATTR_LOADED, DeviceType, FrameType
|
|
11
11
|
from pyplumio.exceptions import UnknownDeviceError
|
12
12
|
from pyplumio.frames import DataFrameDescription, Frame, Request, get_frame_handler
|
13
13
|
from pyplumio.helpers.event_manager import EventManager
|
14
|
-
from pyplumio.helpers.factory import
|
14
|
+
from pyplumio.helpers.factory import create_instance
|
15
15
|
from pyplumio.helpers.parameter import SET_RETRIES, Parameter
|
16
16
|
from pyplumio.helpers.typing import ParameterValueType
|
17
17
|
from pyplumio.structures.network_info import NetworkInfo
|
@@ -160,7 +160,7 @@ class AddressableDevice(Device, ABC):
|
|
160
160
|
|
161
161
|
If value is not available before timeout, retry request.
|
162
162
|
"""
|
163
|
-
request: Request =
|
163
|
+
request: Request = await create_instance(
|
164
164
|
get_frame_handler(frame_type), recipient=self.address
|
165
165
|
)
|
166
166
|
|
@@ -28,7 +28,7 @@ from pyplumio.frames import (
|
|
28
28
|
get_frame_handler,
|
29
29
|
is_known_frame_type,
|
30
30
|
)
|
31
|
-
from pyplumio.helpers.factory import
|
31
|
+
from pyplumio.helpers.factory import create_instance
|
32
32
|
from pyplumio.helpers.parameter import ParameterValues
|
33
33
|
from pyplumio.helpers.schedule import Schedule, ScheduleDay
|
34
34
|
from pyplumio.structures.alerts import ATTR_TOTAL_ALERTS
|
@@ -235,7 +235,7 @@ class EcoMAX(AddressableDevice):
|
|
235
235
|
and not self._has_frame_version(frame_type, version)
|
236
236
|
):
|
237
237
|
# We don't have this frame or it's version has changed.
|
238
|
-
request: Request =
|
238
|
+
request: Request = await create_instance(
|
239
239
|
get_frame_handler(frame_type), recipient=self.address
|
240
240
|
)
|
241
241
|
self.queue.put_nowait(request)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"""Contains a factory helper."""
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import asyncio
|
5
|
+
import importlib
|
6
|
+
import logging
|
7
|
+
from types import ModuleType
|
8
|
+
from typing import Any
|
9
|
+
|
10
|
+
_LOGGER = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
async def _load_module(module_name: str) -> ModuleType:
|
14
|
+
"""Load a module by name."""
|
15
|
+
return await asyncio.get_running_loop().run_in_executor(
|
16
|
+
None, importlib.import_module, f".{module_name}", "pyplumio"
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
async def create_instance(class_path: str, **kwargs: Any) -> Any:
|
21
|
+
"""Return a class instance from the class path."""
|
22
|
+
module_name, class_name = class_path.rsplit(".", 1)
|
23
|
+
try:
|
24
|
+
module = await _load_module(module_name)
|
25
|
+
return getattr(module, class_name)(**kwargs)
|
26
|
+
except Exception:
|
27
|
+
_LOGGER.error("Failed to load module (%s)", class_path)
|
28
|
+
raise
|
@@ -166,6 +166,10 @@ class Parameter(ABC):
|
|
166
166
|
"""Set parameter as no longer pending update."""
|
167
167
|
self._pending_update = False
|
168
168
|
|
169
|
+
async def create_request(self) -> Request:
|
170
|
+
"""Create a request to change the parameter."""
|
171
|
+
raise NotImplementedError
|
172
|
+
|
169
173
|
async def set(self, value: ParameterValueType, retries: int = SET_RETRIES) -> bool:
|
170
174
|
"""Set a parameter value."""
|
171
175
|
if (value := _normalize_parameter_value(value)) == self.values.value:
|
@@ -188,7 +192,7 @@ class Parameter(ABC):
|
|
188
192
|
self.device.unsubscribe(self.description.name, self._confirm_update)
|
189
193
|
return False
|
190
194
|
|
191
|
-
await self.device.queue.put(self.
|
195
|
+
await self.device.queue.put(await self.create_request())
|
192
196
|
await asyncio.sleep(SET_TIMEOUT)
|
193
197
|
retries -= 1
|
194
198
|
|
@@ -223,11 +227,6 @@ class Parameter(ABC):
|
|
223
227
|
"""Return the unit of measurement."""
|
224
228
|
return self.description.unit_of_measurement
|
225
229
|
|
226
|
-
@property
|
227
|
-
def request(self) -> Request:
|
228
|
-
"""Return request to change the parameter."""
|
229
|
-
raise NotImplementedError
|
230
|
-
|
231
230
|
|
232
231
|
class BinaryParameter(Parameter):
|
233
232
|
"""Represents binary device parameter."""
|
@@ -9,7 +9,7 @@ from typing import Final, Literal
|
|
9
9
|
|
10
10
|
from pyplumio.const import STATE_OFF, STATE_ON
|
11
11
|
from pyplumio.devices import AddressableDevice
|
12
|
-
from pyplumio.helpers.factory import
|
12
|
+
from pyplumio.helpers.factory import create_instance
|
13
13
|
from pyplumio.structures.schedules import collect_schedule_data
|
14
14
|
|
15
15
|
TIME_FORMAT: Final = "%H:%M"
|
@@ -158,12 +158,11 @@ class Schedule(Iterable):
|
|
158
158
|
self.saturday,
|
159
159
|
).__iter__()
|
160
160
|
|
161
|
-
def commit(self) -> None:
|
161
|
+
async def commit(self) -> None:
|
162
162
|
"""Commit a weekly schedule to the device."""
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
data=collect_schedule_data(self.name, self.device),
|
168
|
-
)
|
163
|
+
request = await create_instance(
|
164
|
+
"frames.requests.SetScheduleRequest",
|
165
|
+
recipient=self.device.address,
|
166
|
+
data=collect_schedule_data(self.name, self.device),
|
169
167
|
)
|
168
|
+
await self.device.queue.put(request)
|
@@ -4,7 +4,6 @@ from __future__ import annotations
|
|
4
4
|
from abc import ABC, abstractmethod
|
5
5
|
import asyncio
|
6
6
|
from collections.abc import Awaitable, Callable
|
7
|
-
from functools import cache
|
8
7
|
import logging
|
9
8
|
from typing import cast
|
10
9
|
|
@@ -19,7 +18,7 @@ from pyplumio.exceptions import (
|
|
19
18
|
from pyplumio.frames import Frame
|
20
19
|
from pyplumio.frames.requests import StartMasterRequest
|
21
20
|
from pyplumio.helpers.event_manager import EventManager
|
22
|
-
from pyplumio.helpers.factory import
|
21
|
+
from pyplumio.helpers.factory import create_instance
|
23
22
|
from pyplumio.stream import FrameReader, FrameWriter
|
24
23
|
from pyplumio.structures.network_info import (
|
25
24
|
EthernetParameters,
|
@@ -202,7 +201,9 @@ class AsyncProtocol(Protocol, EventManager):
|
|
202
201
|
write_queue.task_done()
|
203
202
|
|
204
203
|
if (response := await reader.read()) is not None:
|
205
|
-
device = self.get_device_entry(
|
204
|
+
device = await self.get_device_entry(
|
205
|
+
cast(DeviceType, response.sender)
|
206
|
+
)
|
206
207
|
read_queue.put_nowait((device, response))
|
207
208
|
|
208
209
|
except FrameDataError as e:
|
@@ -229,16 +230,18 @@ class AsyncProtocol(Protocol, EventManager):
|
|
229
230
|
device.handle_frame(frame)
|
230
231
|
read_queue.task_done()
|
231
232
|
|
232
|
-
|
233
|
-
def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
|
233
|
+
async def get_device_entry(self, device_type: DeviceType) -> AddressableDevice:
|
234
234
|
"""Set up device entry."""
|
235
235
|
handler, name = get_device_handler_and_name(device_type)
|
236
|
-
|
236
|
+
if name not in self.data:
|
237
|
+
self.data[name] = await self._create_device_entry(name, handler)
|
237
238
|
|
238
|
-
|
239
|
+
return self.data[name]
|
240
|
+
|
241
|
+
async def _create_device_entry(self, name: str, handler: str) -> AddressableDevice:
|
239
242
|
"""Create device entry."""
|
240
243
|
write_queue = self.queues[1]
|
241
|
-
device: AddressableDevice =
|
244
|
+
device: AddressableDevice = await create_instance(
|
242
245
|
handler, queue=write_queue, network=self._network
|
243
246
|
)
|
244
247
|
device.dispatch_nowait(ATTR_CONNECTED, True)
|
@@ -9,7 +9,7 @@ from typing import Final
|
|
9
9
|
from pyplumio.const import DeviceType
|
10
10
|
from pyplumio.exceptions import ChecksumError, ReadError
|
11
11
|
from pyplumio.frames import FRAME_START, Frame, bcc, get_frame_handler, struct_header
|
12
|
-
from pyplumio.helpers.factory import
|
12
|
+
from pyplumio.helpers.factory import create_instance
|
13
13
|
from pyplumio.helpers.timeout import timeout
|
14
14
|
|
15
15
|
READER_TIMEOUT: Final = 10
|
@@ -132,7 +132,7 @@ class FrameReader:
|
|
132
132
|
if payload[-2] != bcc(header + payload[:-2]):
|
133
133
|
raise ChecksumError(f"Incorrect frame checksum ({payload[-2]})")
|
134
134
|
|
135
|
-
frame: Frame =
|
135
|
+
frame: Frame = await create_instance(
|
136
136
|
get_frame_handler(frame_type=payload[0]),
|
137
137
|
recipient=recipient,
|
138
138
|
message=payload[1:-2],
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
from collections.abc import Generator
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import Any, Final
|
6
|
+
from typing import Any, Final, cast
|
7
7
|
|
8
8
|
from pyplumio.const import (
|
9
9
|
ATTR_INDEX,
|
@@ -16,7 +16,7 @@ from pyplumio.const import (
|
|
16
16
|
)
|
17
17
|
from pyplumio.devices import AddressableDevice
|
18
18
|
from pyplumio.frames import Request
|
19
|
-
from pyplumio.helpers.factory import
|
19
|
+
from pyplumio.helpers.factory import create_instance
|
20
20
|
from pyplumio.helpers.parameter import (
|
21
21
|
BinaryParameter,
|
22
22
|
BinaryParameterDescription,
|
@@ -44,6 +44,31 @@ class EcomaxParameter(Parameter):
|
|
44
44
|
device: AddressableDevice
|
45
45
|
description: EcomaxParameterDescription
|
46
46
|
|
47
|
+
async def create_request(self) -> Request:
|
48
|
+
"""Create a request to change the parameter."""
|
49
|
+
if self.description.name == ATTR_ECOMAX_CONTROL:
|
50
|
+
cls = "frames.requests.EcomaxControlRequest"
|
51
|
+
data = {ATTR_VALUE: self.values.value}
|
52
|
+
elif self.description.name == ATTR_THERMOSTAT_PROFILE:
|
53
|
+
cls = "frames.requests.SetThermostatParameterRequest"
|
54
|
+
data = {
|
55
|
+
ATTR_INDEX: self._index,
|
56
|
+
ATTR_VALUE: self.values.value,
|
57
|
+
ATTR_OFFSET: 0,
|
58
|
+
ATTR_SIZE: 1,
|
59
|
+
}
|
60
|
+
else:
|
61
|
+
cls = "frames.requests.SetEcomaxParameterRequest"
|
62
|
+
data = {
|
63
|
+
ATTR_INDEX: self._index,
|
64
|
+
ATTR_VALUE: self.values.value,
|
65
|
+
}
|
66
|
+
|
67
|
+
return cast(
|
68
|
+
Request,
|
69
|
+
await create_instance(cls, recipient=self.device.address, data=data),
|
70
|
+
)
|
71
|
+
|
47
72
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
48
73
|
"""Set a parameter value."""
|
49
74
|
if isinstance(value, (int, float)):
|
@@ -72,42 +97,6 @@ class EcomaxParameter(Parameter):
|
|
72
97
|
self.values.max_value - self.description.offset
|
73
98
|
) * self.description.multiplier
|
74
99
|
|
75
|
-
@property
|
76
|
-
def request(self) -> Request:
|
77
|
-
"""Return request to change the parameter."""
|
78
|
-
if self.description.name == ATTR_ECOMAX_CONTROL:
|
79
|
-
request: Request = factory(
|
80
|
-
"frames.requests.EcomaxControlRequest",
|
81
|
-
recipient=self.device.address,
|
82
|
-
data={
|
83
|
-
ATTR_VALUE: self.values.value,
|
84
|
-
},
|
85
|
-
)
|
86
|
-
|
87
|
-
elif self.description.name == ATTR_THERMOSTAT_PROFILE:
|
88
|
-
request = factory(
|
89
|
-
"frames.requests.SetThermostatParameterRequest",
|
90
|
-
recipient=self.device.address,
|
91
|
-
data={
|
92
|
-
ATTR_INDEX: self._index,
|
93
|
-
ATTR_VALUE: self.values.value,
|
94
|
-
ATTR_OFFSET: 0,
|
95
|
-
ATTR_SIZE: 1,
|
96
|
-
},
|
97
|
-
)
|
98
|
-
|
99
|
-
else:
|
100
|
-
request = factory(
|
101
|
-
"frames.requests.SetEcomaxParameterRequest",
|
102
|
-
recipient=self.device.address,
|
103
|
-
data={
|
104
|
-
ATTR_INDEX: self._index,
|
105
|
-
ATTR_VALUE: self.values.value,
|
106
|
-
},
|
107
|
-
)
|
108
|
-
|
109
|
-
return request
|
110
|
-
|
111
100
|
|
112
101
|
class EcomaxBinaryParameter(BinaryParameter, EcomaxParameter):
|
113
102
|
"""Represents an ecoMAX binary parameter."""
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
from collections.abc import Generator
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import TYPE_CHECKING, Any, Final
|
6
|
+
from typing import TYPE_CHECKING, Any, Final, cast
|
7
7
|
|
8
8
|
from pyplumio.const import (
|
9
9
|
ATTR_DEVICE_INDEX,
|
@@ -13,7 +13,7 @@ from pyplumio.const import (
|
|
13
13
|
UnitOfMeasurement,
|
14
14
|
)
|
15
15
|
from pyplumio.frames import Request
|
16
|
-
from pyplumio.helpers.factory import
|
16
|
+
from pyplumio.helpers.factory import create_instance
|
17
17
|
from pyplumio.helpers.parameter import (
|
18
18
|
BinaryParameter,
|
19
19
|
BinaryParameterDescription,
|
@@ -42,6 +42,21 @@ class MixerParameter(Parameter):
|
|
42
42
|
device: Mixer
|
43
43
|
description: MixerParameterDescription
|
44
44
|
|
45
|
+
async def create_request(self) -> Request:
|
46
|
+
"""Create a request to change the parameter."""
|
47
|
+
return cast(
|
48
|
+
Request,
|
49
|
+
await create_instance(
|
50
|
+
"frames.requests.SetMixerParameterRequest",
|
51
|
+
recipient=self.device.parent.address,
|
52
|
+
data={
|
53
|
+
ATTR_INDEX: self._index,
|
54
|
+
ATTR_VALUE: self.values.value,
|
55
|
+
ATTR_DEVICE_INDEX: self.device.index,
|
56
|
+
},
|
57
|
+
),
|
58
|
+
)
|
59
|
+
|
45
60
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
46
61
|
"""Set a parameter value."""
|
47
62
|
if isinstance(value, (int, float)):
|
@@ -70,20 +85,6 @@ class MixerParameter(Parameter):
|
|
70
85
|
self.values.max_value - self.description.offset
|
71
86
|
) * self.description.multiplier
|
72
87
|
|
73
|
-
@property
|
74
|
-
def request(self) -> Request:
|
75
|
-
"""Return request to change the parameter."""
|
76
|
-
request: Request = factory(
|
77
|
-
"frames.requests.SetMixerParameterRequest",
|
78
|
-
recipient=self.device.parent.address,
|
79
|
-
data={
|
80
|
-
ATTR_INDEX: self._index,
|
81
|
-
ATTR_VALUE: self.values.value,
|
82
|
-
ATTR_DEVICE_INDEX: self.device.index,
|
83
|
-
},
|
84
|
-
)
|
85
|
-
return request
|
86
|
-
|
87
88
|
|
88
89
|
class MixerBinaryParameter(BinaryParameter, MixerParameter):
|
89
90
|
"""Represents a mixer binary parameter."""
|
@@ -5,13 +5,13 @@ from collections.abc import Sequence
|
|
5
5
|
from dataclasses import dataclass
|
6
6
|
from functools import reduce
|
7
7
|
from itertools import chain
|
8
|
-
from typing import Any, Final
|
8
|
+
from typing import Any, Final, cast
|
9
9
|
|
10
10
|
from pyplumio.const import ATTR_PARAMETER, ATTR_SCHEDULE, ATTR_SWITCH, ATTR_TYPE
|
11
11
|
from pyplumio.devices import AddressableDevice, Device
|
12
12
|
from pyplumio.exceptions import FrameDataError
|
13
13
|
from pyplumio.frames import Request
|
14
|
-
from pyplumio.helpers.factory import
|
14
|
+
from pyplumio.helpers.factory import create_instance
|
15
15
|
from pyplumio.helpers.parameter import (
|
16
16
|
BinaryParameter,
|
17
17
|
BinaryParameterDescription,
|
@@ -81,16 +81,17 @@ class ScheduleParameter(Parameter):
|
|
81
81
|
|
82
82
|
device: AddressableDevice
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
"""Return request to change the parameter."""
|
84
|
+
async def create_request(self) -> Request:
|
85
|
+
"""Create a request to change the parameter."""
|
87
86
|
schedule_name, _ = self.description.name.split("_schedule_", 1)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
return cast(
|
88
|
+
Request,
|
89
|
+
await create_instance(
|
90
|
+
"frames.requests.SetScheduleRequest",
|
91
|
+
recipient=self.device.address,
|
92
|
+
data=collect_schedule_data(schedule_name, self.device),
|
93
|
+
),
|
92
94
|
)
|
93
|
-
return request
|
94
95
|
|
95
96
|
|
96
97
|
class ScheduleBinaryParameter(ScheduleParameter, BinaryParameter):
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
from collections.abc import Generator
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import TYPE_CHECKING, Any, Final
|
6
|
+
from typing import TYPE_CHECKING, Any, Final, cast
|
7
7
|
|
8
8
|
from pyplumio.const import (
|
9
9
|
ATTR_INDEX,
|
@@ -14,7 +14,7 @@ from pyplumio.const import (
|
|
14
14
|
)
|
15
15
|
from pyplumio.devices import AddressableDevice
|
16
16
|
from pyplumio.frames import Request
|
17
|
-
from pyplumio.helpers.factory import
|
17
|
+
from pyplumio.helpers.factory import create_instance
|
18
18
|
from pyplumio.helpers.parameter import (
|
19
19
|
BinaryParameter,
|
20
20
|
BinaryParameterDescription,
|
@@ -59,6 +59,24 @@ class ThermostatParameter(Parameter):
|
|
59
59
|
self.offset = offset
|
60
60
|
super().__init__(device, values, description, index)
|
61
61
|
|
62
|
+
async def create_request(self) -> Request:
|
63
|
+
"""Create a request to change the parameter."""
|
64
|
+
return cast(
|
65
|
+
Request,
|
66
|
+
await create_instance(
|
67
|
+
"frames.requests.SetThermostatParameterRequest",
|
68
|
+
recipient=self.device.parent.address,
|
69
|
+
data={
|
70
|
+
# Increase the index by one to account for thermostat
|
71
|
+
# profile, which is being set at ecoMAX device level.
|
72
|
+
ATTR_INDEX: self._index + 1,
|
73
|
+
ATTR_VALUE: self.values.value,
|
74
|
+
ATTR_OFFSET: self.offset,
|
75
|
+
ATTR_SIZE: self.description.size,
|
76
|
+
},
|
77
|
+
),
|
78
|
+
)
|
79
|
+
|
62
80
|
async def set(self, value: ParameterValueType, retries: int = 5) -> bool:
|
63
81
|
"""Set a parameter value."""
|
64
82
|
if isinstance(value, (int, float)):
|
@@ -81,23 +99,6 @@ class ThermostatParameter(Parameter):
|
|
81
99
|
"""Return the maximum allowed value."""
|
82
100
|
return self.values.max_value * self.description.multiplier
|
83
101
|
|
84
|
-
@property
|
85
|
-
def request(self) -> Request:
|
86
|
-
"""Return request to change the parameter."""
|
87
|
-
request: Request = factory(
|
88
|
-
"frames.requests.SetThermostatParameterRequest",
|
89
|
-
recipient=self.device.parent.address,
|
90
|
-
data={
|
91
|
-
# Increase the index by one to account for thermostat
|
92
|
-
# profile, which is being set at ecoMAX device level.
|
93
|
-
ATTR_INDEX: self._index + 1,
|
94
|
-
ATTR_VALUE: self.values.value,
|
95
|
-
ATTR_OFFSET: self.offset,
|
96
|
-
ATTR_SIZE: self.description.size,
|
97
|
-
},
|
98
|
-
)
|
99
|
-
return request
|
100
|
-
|
101
102
|
|
102
103
|
class ThermostatBinaryParameter(BinaryParameter, ThermostatParameter):
|
103
104
|
"""Represents a thermostat binary parameter."""
|
@@ -33,23 +33,23 @@ dynamic = ["version"]
|
|
33
33
|
[project.optional-dependencies]
|
34
34
|
test = [
|
35
35
|
"codespell==2.2.6",
|
36
|
-
"coverage==7.
|
37
|
-
"mypy==1.
|
36
|
+
"coverage==7.5.1",
|
37
|
+
"mypy==1.10.0",
|
38
38
|
"pyserial-asyncio-fast==0.11",
|
39
|
-
"pytest==8.
|
40
|
-
"pytest-asyncio==0.23.
|
41
|
-
"ruff==0.3
|
42
|
-
"tox==4.
|
43
|
-
"types-pyserial==3.5.0.
|
39
|
+
"pytest==8.2.0",
|
40
|
+
"pytest-asyncio==0.23.6",
|
41
|
+
"ruff==0.4.3",
|
42
|
+
"tox==4.15.0",
|
43
|
+
"types-pyserial==3.5.0.20240311"
|
44
44
|
]
|
45
45
|
docs = [
|
46
|
-
"sphinx==7.
|
46
|
+
"sphinx==7.3.7",
|
47
47
|
"sphinx_rtd_theme==2.0.0",
|
48
48
|
"readthedocs-sphinx-search==0.3.2"
|
49
49
|
]
|
50
50
|
dev = [
|
51
51
|
"pyplumio[test,docs]",
|
52
|
-
"pre-commit==3.
|
52
|
+
"pre-commit==3.7.0",
|
53
53
|
"tomli==2.0.1"
|
54
54
|
]
|
55
55
|
|