aiobmsble 0.2.1__tar.gz → 0.2.3__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.
- {aiobmsble-0.2.1/aiobmsble.egg-info → aiobmsble-0.2.3}/PKG-INFO +2 -2
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/__init__.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/__main__.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/basebms.py +10 -1
- aiobmsble-0.2.3/aiobmsble/bms/__init__.py +5 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/abc_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ant_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/braunpwr_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/cbtpwr_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/cbtpwr_vb_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/daly_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/dpwrcore_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/dummy_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ecoworthy_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ective_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ej_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/felicity_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/jbd_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/jikong_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/neey_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ogt_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/pro_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/redodo_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/renogy_bms.py +4 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/renogy_pro_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/roypow_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/seplos_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/seplos_v2_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/tdt_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/tianpwr_bms.py +5 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/utils.py +15 -5
- {aiobmsble-0.2.1 → aiobmsble-0.2.3/aiobmsble.egg-info}/PKG-INFO +2 -2
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/requires.txt +1 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/pyproject.toml +101 -97
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_basebms.py +7 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_utils.py +4 -5
- aiobmsble-0.2.1/aiobmsble/bms/__init__.py +0 -1
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/LICENSE +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/MANIFEST.in +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/README.md +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/SOURCES.txt +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/dependency_links.txt +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/entry_points.txt +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/top_level.txt +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/setup.cfg +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_examples.py +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_fuzzing.py +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_main.py +0 -0
- {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_plugins.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: aiobmsble
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.3
|
4
4
|
Summary: Asynchronous Python library to query battery management systems via Bluetooth Low Energy.
|
5
5
|
Author: Patrick Loschmidt
|
6
6
|
Maintainer: Patrick Loschmidt
|
@@ -19,7 +19,7 @@ Requires-Python: >=3.12
|
|
19
19
|
Description-Content-Type: text/markdown
|
20
20
|
License-File: LICENSE
|
21
21
|
Requires-Dist: bleak~=1.1.0
|
22
|
-
Requires-Dist: bleak-retry-connector
|
22
|
+
Requires-Dist: bleak-retry-connector>=4.0.2
|
23
23
|
Requires-Dist: asyncio
|
24
24
|
Requires-Dist: logging
|
25
25
|
Requires-Dist: statistics
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Package for battery management systems (BMS) via Bluetooth LE.
|
1
|
+
"""Package for battery management systems (BMS) via Bluetooth LE (aiobmsble).
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from collections.abc import Callable
|
4
8
|
from enum import IntEnum
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Base class defintion for battery management systems (BMS).
|
1
|
+
"""Base class defintion for battery management systems (BMS).
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from abc import ABC, abstractmethod
|
4
8
|
import asyncio
|
@@ -79,6 +83,11 @@ class BaseBMS(ABC):
|
|
79
83
|
self._data: bytearray = bytearray()
|
80
84
|
self._data_event: Final[asyncio.Event] = asyncio.Event()
|
81
85
|
|
86
|
+
@classmethod
|
87
|
+
def get_bms_module(cls) -> str:
|
88
|
+
"""Return BMS module name, e.g. aiobmsble.bms.dummy_bms."""
|
89
|
+
return cls.__module__
|
90
|
+
|
82
91
|
@staticmethod
|
83
92
|
@abstractmethod
|
84
93
|
def matcher_dict_list() -> list[MatcherPattern]:
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support CBT Power VB series BMS.
|
1
|
+
"""Module to support CBT Power VB series BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from string import hexdigits
|
4
8
|
from typing import Final
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support D-powercore Smart BMS.
|
1
|
+
"""Module to support D-powercore Smart BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from enum import IntEnum
|
4
8
|
from string import hexdigits
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Dummy BMS.
|
1
|
+
"""Module to support Dummy BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from bleak.backends.characteristic import BleakGATTCharacteristic
|
4
8
|
from bleak.backends.device import BLEDevice
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Felicity BMS.
|
1
|
+
"""Module to support Felicity BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from collections.abc import Callable
|
4
8
|
from json import JSONDecodeError, loads
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Neey Smart BMS.
|
1
|
+
"""Module to support Neey Smart BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from collections.abc import Callable
|
4
8
|
from struct import unpack_from
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Offgridtec Smart Pro BMS.
|
1
|
+
"""Module to support Offgridtec Smart Pro BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from collections.abc import Callable
|
4
8
|
from string import digits, hexdigits
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Renogy Pro BMS.
|
1
|
+
"""Module to support Renogy Pro BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from bleak.backends.characteristic import BleakGATTCharacteristic
|
4
8
|
from bleak.backends.device import BLEDevice
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Module to support Seplos V3 Smart BMS.
|
1
|
+
"""Module to support Seplos V3 Smart BMS.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from collections.abc import Callable
|
4
8
|
from typing import Any, Final
|
@@ -1,4 +1,8 @@
|
|
1
|
-
"""Utilitiy/Support functions for aiobmsble.
|
1
|
+
"""Utilitiy/Support functions for aiobmsble.
|
2
|
+
|
3
|
+
Project: aiobmsble, https://pypi.org/p/aiobmsble/
|
4
|
+
License: Apache-2.0, http://www.apache.org/licenses/
|
5
|
+
"""
|
2
6
|
|
3
7
|
from fnmatch import translate
|
4
8
|
from functools import lru_cache
|
@@ -6,11 +10,15 @@ import importlib
|
|
6
10
|
import pkgutil
|
7
11
|
import re
|
8
12
|
from types import ModuleType
|
13
|
+
from typing import Final
|
9
14
|
|
10
15
|
from bleak.backends.scanner import AdvertisementData
|
11
16
|
|
12
17
|
from aiobmsble import MatcherPattern
|
13
18
|
from aiobmsble.basebms import BaseBMS
|
19
|
+
import aiobmsble.bms
|
20
|
+
|
21
|
+
_MODULE_POSTFIX: Final[str] = "_bms"
|
14
22
|
|
15
23
|
|
16
24
|
def _advertisement_matches(
|
@@ -78,8 +86,8 @@ def load_bms_plugins() -> set[ModuleType]:
|
|
78
86
|
"""
|
79
87
|
return {
|
80
88
|
importlib.import_module(f"aiobmsble.bms.{module_name}")
|
81
|
-
for _, module_name, _ in pkgutil.iter_modules(
|
82
|
-
if module_name.endswith(
|
89
|
+
for _, module_name, _ in pkgutil.iter_modules(aiobmsble.bms.__path__)
|
90
|
+
if module_name.endswith(_MODULE_POSTFIX)
|
83
91
|
}
|
84
92
|
|
85
93
|
|
@@ -87,14 +95,16 @@ def bms_cls(name: str) -> type[BaseBMS] | None:
|
|
87
95
|
"""Return the BMS class that is defined by the name argument.
|
88
96
|
|
89
97
|
Args:
|
90
|
-
name (str): The name of the BMS type
|
98
|
+
name (str): The name of the BMS type (filename of the module)
|
91
99
|
|
92
100
|
Returns:
|
93
101
|
type[BaseBMS] | None: If the BMS class defined by name is found, None otherwise.
|
94
102
|
|
95
103
|
"""
|
104
|
+
if not name.endswith(_MODULE_POSTFIX):
|
105
|
+
return None
|
96
106
|
try:
|
97
|
-
bms_module: ModuleType = importlib.import_module(f"aiobmsble.bms.{name}
|
107
|
+
bms_module: ModuleType = importlib.import_module(f"aiobmsble.bms.{name}")
|
98
108
|
except ModuleNotFoundError:
|
99
109
|
return None
|
100
110
|
return bms_module.BMS
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: aiobmsble
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.3
|
4
4
|
Summary: Asynchronous Python library to query battery management systems via Bluetooth Low Energy.
|
5
5
|
Author: Patrick Loschmidt
|
6
6
|
Maintainer: Patrick Loschmidt
|
@@ -19,7 +19,7 @@ Requires-Python: >=3.12
|
|
19
19
|
Description-Content-Type: text/markdown
|
20
20
|
License-File: LICENSE
|
21
21
|
Requires-Dist: bleak~=1.1.0
|
22
|
-
Requires-Dist: bleak-retry-connector
|
22
|
+
Requires-Dist: bleak-retry-connector>=4.0.2
|
23
23
|
Requires-Dist: asyncio
|
24
24
|
Requires-Dist: logging
|
25
25
|
Requires-Dist: statistics
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "aiobmsble"
|
7
|
-
version = "0.2.
|
7
|
+
version = "0.2.3"
|
8
8
|
requires-python = ">=3.12"
|
9
9
|
description = "Asynchronous Python library to query battery management systems via Bluetooth Low Energy."
|
10
10
|
readme = "README.md"
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
28
28
|
]
|
29
29
|
dependencies = [
|
30
30
|
"bleak~=1.1.0",
|
31
|
-
"bleak-retry-connector
|
31
|
+
"bleak-retry-connector>=4.0.2",
|
32
32
|
"asyncio",
|
33
33
|
"logging",
|
34
34
|
"statistics",
|
@@ -59,62 +59,58 @@ testpaths = [
|
|
59
59
|
asyncio_mode = "auto"
|
60
60
|
asyncio_default_fixture_loop_scope = "function"
|
61
61
|
|
62
|
-
# ruff settings from HA 2025.
|
62
|
+
# ruff settings from HA 2025.9.0
|
63
63
|
[tool.ruff]
|
64
|
-
required-version = "
|
64
|
+
required-version = "~=0.12.1"
|
65
65
|
|
66
66
|
[tool.ruff.lint]
|
67
67
|
select = [
|
68
|
-
"A001",
|
69
|
-
"
|
70
|
-
"
|
71
|
-
"
|
72
|
-
"
|
73
|
-
"
|
74
|
-
"
|
75
|
-
"
|
76
|
-
"
|
77
|
-
"
|
78
|
-
"
|
79
|
-
"
|
80
|
-
"
|
81
|
-
"
|
82
|
-
"
|
83
|
-
"
|
84
|
-
"
|
85
|
-
"B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)?
|
86
|
-
"B035", # Dictionary comprehension uses static key
|
87
|
-
"B904", # Use raise from to specify exception cause
|
88
|
-
"B905", # zip() without an explicit strict= parameter
|
68
|
+
"A001", # Variable {name} is shadowing a Python builtin
|
69
|
+
"ASYNC", # flake8-async
|
70
|
+
"B002", # Python does not support the unary prefix increment
|
71
|
+
"B005", # Using .strip() with multi-character strings is misleading
|
72
|
+
"B007", # Loop control variable {name} not used within loop body
|
73
|
+
# "B009", # Do not call getattr with a constant attribute value. It is not any safer than normal property access.
|
74
|
+
"B014", # Exception handler with duplicate exception
|
75
|
+
"B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it.
|
76
|
+
"B017", # pytest.raises(BaseException) should be considered evil
|
77
|
+
"B018", # Found useless attribute access. Either assign it to a variable or remove it.
|
78
|
+
"B023", # Function definition does not bind loop variable {name}
|
79
|
+
"B024", # `{name}` is an abstract base class, but it has no abstract methods or properties
|
80
|
+
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
|
81
|
+
"B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)?
|
82
|
+
"B035", # Dictionary comprehension uses static key
|
83
|
+
"B904", # Use raise from to specify exception cause
|
84
|
+
"B905", # zip() without an explicit strict= parameter
|
89
85
|
"BLE",
|
90
|
-
"C",
|
86
|
+
"C", # complexity
|
91
87
|
"COM818", # Trailing comma on bare tuple prohibited
|
92
|
-
"D",
|
88
|
+
"D", # docstrings
|
93
89
|
"DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
|
94
90
|
"DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
|
95
|
-
"E",
|
96
|
-
"F",
|
97
|
-
"F541",
|
98
|
-
"FLY",
|
99
|
-
"FURB",
|
100
|
-
"G",
|
101
|
-
"I",
|
102
|
-
"INP",
|
103
|
-
"ISC",
|
91
|
+
"E", # pycodestyle
|
92
|
+
"F", # pyflakes/autoflake
|
93
|
+
"F541", # f-string without any placeholders
|
94
|
+
"FLY", # flynt
|
95
|
+
"FURB", # refurb
|
96
|
+
"G", # flake8-logging-format
|
97
|
+
"I", # isort
|
98
|
+
"INP", # flake8-no-pep420
|
99
|
+
"ISC", # flake8-implicit-str-concat
|
104
100
|
"ICN001", # import concentions; {name} should be imported as {asname}
|
105
|
-
"LOG",
|
106
|
-
"N804",
|
107
|
-
"N805",
|
108
|
-
"N815",
|
109
|
-
"PERF",
|
110
|
-
"PGH",
|
111
|
-
"PIE",
|
112
|
-
"PL",
|
113
|
-
"PT",
|
114
|
-
"PTH",
|
115
|
-
"PYI",
|
116
|
-
"RET",
|
117
|
-
"RSE",
|
101
|
+
"LOG", # flake8-logging
|
102
|
+
"N804", # First argument of a class method should be named cls
|
103
|
+
"N805", # First argument of a method should be named self
|
104
|
+
"N815", # Variable {name} in class scope should not be mixedCase
|
105
|
+
"PERF", # Perflint
|
106
|
+
"PGH", # pygrep-hooks
|
107
|
+
"PIE", # flake8-pie
|
108
|
+
"PL", # pylint
|
109
|
+
"PT", # flake8-pytest-style
|
110
|
+
"PTH", # flake8-pathlib
|
111
|
+
"PYI", # flake8-pyi
|
112
|
+
"RET", # flake8-return
|
113
|
+
"RSE", # flake8-raise
|
118
114
|
"RUF005", # Consider iterable unpacking instead of concatenation
|
119
115
|
"RUF006", # Store a reference to the return value of asyncio.create_task
|
120
116
|
"RUF007", # Prefer itertools.pairwise() over zip() when iterating over successive pairs
|
@@ -138,44 +134,46 @@ select = [
|
|
138
134
|
"RUF100", # Unused `noqa` directive
|
139
135
|
"RUF101", # noqa directives that use redirected rule codes
|
140
136
|
"RUF200", # Failed to parse pyproject.toml: {message}
|
141
|
-
"S102",
|
142
|
-
"S103",
|
143
|
-
"S108",
|
144
|
-
"S306",
|
145
|
-
"S307",
|
146
|
-
"S313",
|
147
|
-
"S314",
|
148
|
-
"S315",
|
149
|
-
"S316",
|
150
|
-
"S317",
|
151
|
-
"S318",
|
152
|
-
"S319",
|
153
|
-
"S601",
|
154
|
-
"S602",
|
155
|
-
"S604",
|
156
|
-
"S608",
|
157
|
-
"S609",
|
158
|
-
"SIM",
|
159
|
-
"SLF",
|
160
|
-
"SLOT",
|
161
|
-
"T100",
|
162
|
-
"T20",
|
163
|
-
"TC",
|
164
|
-
"TID",
|
165
|
-
"TRY",
|
166
|
-
"UP",
|
167
|
-
"UP031",
|
168
|
-
"UP032",
|
169
|
-
"W",
|
137
|
+
"S102", # Use of exec detected
|
138
|
+
"S103", # bad-file-permissions
|
139
|
+
"S108", # hardcoded-temp-file
|
140
|
+
"S306", # suspicious-mktemp-usage
|
141
|
+
"S307", # suspicious-eval-usage
|
142
|
+
"S313", # suspicious-xmlc-element-tree-usage
|
143
|
+
"S314", # suspicious-xml-element-tree-usage
|
144
|
+
"S315", # suspicious-xml-expat-reader-usage
|
145
|
+
"S316", # suspicious-xml-expat-builder-usage
|
146
|
+
"S317", # suspicious-xml-sax-usage
|
147
|
+
"S318", # suspicious-xml-mini-dom-usage
|
148
|
+
"S319", # suspicious-xml-pull-dom-usage
|
149
|
+
"S601", # paramiko-call
|
150
|
+
"S602", # subprocess-popen-with-shell-equals-true
|
151
|
+
"S604", # call-with-shell-equals-true
|
152
|
+
"S608", # hardcoded-sql-expression
|
153
|
+
"S609", # unix-command-wildcard-injection
|
154
|
+
"SIM", # flake8-simplify
|
155
|
+
"SLF", # flake8-self
|
156
|
+
"SLOT", # flake8-slots
|
157
|
+
"T100", # Trace found: {name} used
|
158
|
+
"T20", # flake8-print
|
159
|
+
"TC", # flake8-type-checking
|
160
|
+
"TID", # Tidy imports
|
161
|
+
"TRY", # tryceratops
|
162
|
+
"UP", # pyupgrade
|
163
|
+
"UP031", # Use format specifiers instead of percent format
|
164
|
+
"UP032", # Use f-string instead of `format` call
|
165
|
+
"W", # pycodestyle
|
170
166
|
]
|
171
167
|
|
172
168
|
ignore = [
|
173
|
-
"
|
174
|
-
"
|
175
|
-
"
|
176
|
-
"
|
177
|
-
"
|
178
|
-
"
|
169
|
+
"ASYNC109", # Async function definition with a `timeout` parameter Use `asyncio.timeout` instead
|
170
|
+
"ASYNC110", # Use `asyncio.Event` instead of awaiting `asyncio.sleep` in a `while` loop
|
171
|
+
"D202", # No blank lines allowed after function docstring
|
172
|
+
"D203", # 1 blank line required before class docstring
|
173
|
+
"D213", # Multi-line docstring summary should start at the second line
|
174
|
+
"D406", # Section name should end with a newline
|
175
|
+
"D407", # Section name underlining
|
176
|
+
"E501", # line too long
|
179
177
|
|
180
178
|
# "PLC1901", # {existing} can be simplified to {replacement} as an empty string is falsey; too many false positives
|
181
179
|
# "PLR0911", # Too many return statements ({returns} > {max_returns})
|
@@ -183,27 +181,33 @@ ignore = [
|
|
183
181
|
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
|
184
182
|
# "PLR0915", # Too many statements ({statements} > {max_statements})
|
185
183
|
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
|
184
|
+
"PLW1641", # __eq__ without __hash__
|
186
185
|
# "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
|
187
|
-
# "PT011",
|
188
|
-
"PT018",
|
189
|
-
# "RUF001",
|
190
|
-
# "RUF002",
|
191
|
-
# "RUF003",
|
192
|
-
# "RUF015",
|
193
|
-
"SIM102",
|
194
|
-
# "SIM103",
|
195
|
-
# "SIM108",
|
196
|
-
# "SIM115",
|
186
|
+
# "PT011", # pytest.raises({exception}) is too broad, set the `match` parameter or use a more specific exception
|
187
|
+
"PT018", # Assertion should be broken down into multiple parts
|
188
|
+
# "RUF001", # String contains ambiguous unicode character.
|
189
|
+
# "RUF002", # Docstring contains ambiguous unicode character.
|
190
|
+
# "RUF003", # Comment contains ambiguous unicode character.
|
191
|
+
# "RUF015", # Prefer next(...) over single element slice
|
192
|
+
"SIM102", # Use a single if statement instead of nested if statements
|
193
|
+
# "SIM103", # Return the condition {condition} directly
|
194
|
+
# "SIM108", # Use ternary operator {contents} instead of if-else-block
|
195
|
+
# "SIM115", # Use context handler for opening files
|
197
196
|
|
198
197
|
# Moving imports into type-checking blocks can mess with pytest.patch()
|
199
198
|
"TC001", # Move application import {} into a type-checking block
|
200
199
|
"TC002", # Move third-party import {} into a type-checking block
|
201
200
|
"TC003", # Move standard library import {} into a type-checking block
|
201
|
+
# Quotes for typing.cast generally not necessary, only for performance critical paths
|
202
|
+
"TC006", # Add quotes to type expression in typing.cast()
|
202
203
|
|
203
204
|
"TRY003", # Avoid specifying long messages outside the exception class
|
204
205
|
"TRY400", # Use `logging.exception` instead of `logging.error`
|
205
206
|
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
|
206
|
-
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
|
207
|
+
# "UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
|
208
|
+
# "UP046", # Non PEP 695 generic class
|
209
|
+
# "UP047", # Non PEP 696 generic function
|
210
|
+
# "UP049", # Avoid private type parameter names
|
207
211
|
|
208
212
|
# May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
209
213
|
"W191",
|
@@ -215,12 +219,12 @@ ignore = [
|
|
215
219
|
"Q",
|
216
220
|
"COM812",
|
217
221
|
"COM819",
|
218
|
-
"ISC001",
|
219
222
|
|
220
223
|
# Disabled because ruff does not understand type of __all__ generated by a function
|
221
|
-
"PLE0605"
|
224
|
+
"PLE0605",
|
222
225
|
]
|
223
226
|
|
227
|
+
|
224
228
|
[tool.ruff.lint.isort]
|
225
229
|
force-sort-within-sections = true
|
226
230
|
known-first-party = [
|
@@ -14,6 +14,7 @@ import pytest
|
|
14
14
|
|
15
15
|
from aiobmsble import BMSdp, BMSsample, MatcherPattern
|
16
16
|
from aiobmsble.basebms import BaseBMS, crc8, crc_modbus, crc_sum, crc_xmodem, lrc_modbus
|
17
|
+
from aiobmsble.bms.dummy_bms import BMS as DummyBMS
|
17
18
|
|
18
19
|
from .bluetooth import generate_ble_device
|
19
20
|
from .conftest import MockBleakClient
|
@@ -315,6 +316,12 @@ async def test_wr_mode_reset(
|
|
315
316
|
assert bms._inv_wr_mode is None
|
316
317
|
|
317
318
|
|
319
|
+
def test_get_bms_module() -> None:
|
320
|
+
"""Check that basebms and dummy_bms return correct module name."""
|
321
|
+
assert BaseBMS.get_bms_module() == "aiobmsble.basebms"
|
322
|
+
assert DummyBMS.get_bms_module() == "aiobmsble.bms.dummy_bms"
|
323
|
+
|
324
|
+
|
318
325
|
async def test_no_notify(
|
319
326
|
patch_bleak_client: Callable[..., None], caplog: pytest.LogCaptureFixture
|
320
327
|
) -> None:
|
@@ -55,15 +55,14 @@ def test_bms_identify(plugin: ModuleType) -> None:
|
|
55
55
|
def test_bms_cls(plugin: ModuleType) -> None:
|
56
56
|
"""Test that a BMS class is correctly returned from its name."""
|
57
57
|
# strip _bms to get only type
|
58
|
-
bms_type: str = getattr(plugin, "__name__", "").rsplit(".", 1)[-1]
|
58
|
+
bms_type: str = getattr(plugin, "__name__", "").rsplit(".", 1)[-1]
|
59
59
|
bms_class: type[BaseBMS] | None = bms_cls(bms_type)
|
60
60
|
assert bms_class == plugin.BMS
|
61
61
|
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
bms_type: str = "unvailable_bms"
|
63
|
+
@pytest.mark.parametrize("bms_type", ["unavailable_bms", "ignore_me"])
|
64
|
+
def test_bms_cls_none(bms_type: str) -> None:
|
65
|
+
"""Test that a BMS class is None when name is not correct."""
|
67
66
|
bms_class: type[BaseBMS] | None = bms_cls(bms_type)
|
68
67
|
assert bms_class is None
|
69
68
|
|
@@ -1 +0,0 @@
|
|
1
|
-
"""Package for battery management systems (BMS) plugins."""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|