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.
Files changed (49) hide show
  1. {aiobmsble-0.2.1/aiobmsble.egg-info → aiobmsble-0.2.3}/PKG-INFO +2 -2
  2. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/__init__.py +5 -1
  3. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/__main__.py +5 -1
  4. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/basebms.py +10 -1
  5. aiobmsble-0.2.3/aiobmsble/bms/__init__.py +5 -0
  6. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/abc_bms.py +5 -1
  7. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ant_bms.py +5 -1
  8. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/braunpwr_bms.py +5 -1
  9. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/cbtpwr_bms.py +5 -1
  10. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/cbtpwr_vb_bms.py +5 -1
  11. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/daly_bms.py +5 -1
  12. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/dpwrcore_bms.py +5 -1
  13. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/dummy_bms.py +5 -1
  14. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ecoworthy_bms.py +5 -1
  15. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ective_bms.py +5 -1
  16. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ej_bms.py +5 -1
  17. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/felicity_bms.py +5 -1
  18. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/jbd_bms.py +5 -1
  19. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/jikong_bms.py +5 -1
  20. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/neey_bms.py +5 -1
  21. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/ogt_bms.py +5 -1
  22. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/pro_bms.py +5 -1
  23. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/redodo_bms.py +5 -1
  24. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/renogy_bms.py +4 -1
  25. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/renogy_pro_bms.py +5 -1
  26. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/roypow_bms.py +5 -1
  27. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/seplos_bms.py +5 -1
  28. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/seplos_v2_bms.py +5 -1
  29. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/tdt_bms.py +5 -1
  30. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/bms/tianpwr_bms.py +5 -1
  31. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble/utils.py +15 -5
  32. {aiobmsble-0.2.1 → aiobmsble-0.2.3/aiobmsble.egg-info}/PKG-INFO +2 -2
  33. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/requires.txt +1 -1
  34. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/pyproject.toml +101 -97
  35. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_basebms.py +7 -0
  36. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_utils.py +4 -5
  37. aiobmsble-0.2.1/aiobmsble/bms/__init__.py +0 -1
  38. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/LICENSE +0 -0
  39. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/MANIFEST.in +0 -0
  40. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/README.md +0 -0
  41. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/SOURCES.txt +0 -0
  42. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/dependency_links.txt +0 -0
  43. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/entry_points.txt +0 -0
  44. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/aiobmsble.egg-info/top_level.txt +0 -0
  45. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/setup.cfg +0 -0
  46. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_examples.py +0 -0
  47. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_fuzzing.py +0 -0
  48. {aiobmsble-0.2.1 → aiobmsble-0.2.3}/tests/test_main.py +0 -0
  49. {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.1
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~=4.0.2
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
- """Example function for package usage."""
1
+ """Example script for aiobmsble package usage.
2
+
3
+ Project: aiobmsble, https://pypi.org/p/aiobmsble/
4
+ License: Apache-2.0, http://www.apache.org/licenses/
5
+ """
2
6
 
3
7
  import argparse
4
8
  import asyncio
@@ -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]:
@@ -0,0 +1,5 @@
1
+ """Package for battery management systems (BMS) plugins.
2
+
3
+ Project: aiobmsble, https://pypi.org/p/aiobmsble/
4
+ License: Apache-2.0, http://www.apache.org/licenses/
5
+ """
@@ -1,4 +1,8 @@
1
- """Module to support ABC BMS."""
1
+ """Module to support ABC 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
  import contextlib
4
8
  from typing import Final
@@ -1,4 +1,8 @@
1
- """Module to support ANT BMS."""
1
+ """Module to support ANT 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 typing import Final
4
8
 
@@ -1,4 +1,8 @@
1
- """Module to support Braun Power BMS."""
1
+ """Module to support Braun Power 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 typing import Final
4
8
 
@@ -1,4 +1,8 @@
1
- """Module to support CBT Power Smart BMS."""
1
+ """Module to support CBT Power 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 typing import Final
4
8
 
@@ -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 Daly Smart BMS."""
1
+ """Module to support Daly 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 typing import Final
4
8
 
@@ -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 ECO-WORTHY BMS."""
1
+ """Module to support ECO-WORTHY 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
  import asyncio
4
8
  from typing import Final
@@ -1,4 +1,8 @@
1
- """Module to support Ective BMS."""
1
+ """Module to support Ective 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
  import asyncio
4
8
  from string import hexdigits
@@ -1,4 +1,8 @@
1
- """Module to support E&J Technology BMS."""
1
+ """Module to support E&J Technology 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 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 JBD Smart BMS."""
1
+ """Module to support JBD 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 typing import Final
4
8
 
@@ -1,4 +1,8 @@
1
- """Module to support Jikong Smart BMS."""
1
+ """Module to support Jikong 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
  import asyncio
4
8
  from typing import Final
@@ -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 Pro BMS."""
1
+ """Module to support 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
  import asyncio
4
8
  from typing import Final
@@ -1,4 +1,8 @@
1
- """Module to support Redodo BMS."""
1
+ """Module to support Redodo 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 typing import Final
4
8
 
@@ -1,4 +1,7 @@
1
- """Module to support Renogy BMS."""
1
+ """Module to support Renogy BMS.
2
+
3
+ Project: aiobmsble, https://pypi.org/p/aiobmsble/
4
+ """
2
5
 
3
6
  from typing import Final
4
7
 
@@ -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 RoyPow BMS."""
1
+ """Module to support RoyPow 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 typing import Final
4
8
 
@@ -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
- """Module to support Seplos v2 BMS."""
1
+ """Module to support Seplos v2 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 typing import Final
4
8
 
@@ -1,4 +1,8 @@
1
- """Module to support TDT BMS."""
1
+ """Module to support TDT 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 typing import Final
4
8
 
@@ -1,4 +1,8 @@
1
- """Module to support TianPwr BMS."""
1
+ """Module to support TianPwr 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 typing import Final
4
8
 
@@ -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(["aiobmsble/bms"])
82
- if module_name.endswith("_bms")
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}_bms")
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.1
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~=4.0.2
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,5 +1,5 @@
1
1
  bleak~=1.1.0
2
- bleak-retry-connector~=4.0.2
2
+ bleak-retry-connector>=4.0.2
3
3
  asyncio
4
4
  logging
5
5
  statistics
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aiobmsble"
7
- version = "0.2.1"
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~=4.0.2",
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.2.2
62
+ # ruff settings from HA 2025.9.0
63
63
  [tool.ruff]
64
- required-version = ">=0.9.1"
64
+ required-version = "~=0.12.1"
65
65
 
66
66
  [tool.ruff.lint]
67
67
  select = [
68
- "A001", # Variable {name} is shadowing a Python builtin
69
- "ASYNC210", # Async functions should not call blocking HTTP methods
70
- "ASYNC220", # Async functions should not create subprocesses with blocking methods
71
- "ASYNC221", # Async functions should not run processes with blocking methods
72
- "ASYNC222", # Async functions should not wait on processes with blocking methods
73
- "ASYNC230", # Async functions should not open files with blocking methods like open
74
- "ASYNC251", # Async functions should not call time.sleep
75
- "B002", # Python does not support the unary prefix increment
76
- "B005", # Using .strip() with multi-character strings is misleading
77
- "B007", # Loop control variable {name} not used within loop body
78
- "B014", # Exception handler with duplicate exception
79
- "B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it.
80
- "B017", # pytest.raises(BaseException) should be considered evil
81
- "B018", # Found useless attribute access. Either assign it to a variable or remove it.
82
- "B023", # Function definition does not bind loop variable {name}
83
- "B024", # `{name}` is an abstract base class, but it has no abstract methods or properties
84
- "B026", # Star-arg unpacking after a keyword argument is strongly discouraged
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", # complexity
86
+ "C", # complexity
91
87
  "COM818", # Trailing comma on bare tuple prohibited
92
- "D", # docstrings
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", # pycodestyle
96
- "F", # pyflakes/autoflake
97
- "F541", # f-string without any placeholders
98
- "FLY", # flynt
99
- "FURB", # refurb
100
- "G", # flake8-logging-format
101
- "I", # isort
102
- "INP", # flake8-no-pep420
103
- "ISC", # flake8-implicit-str-concat
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", # flake8-logging
106
- "N804", # First argument of a class method should be named cls
107
- "N805", # First argument of a method should be named self
108
- "N815", # Variable {name} in class scope should not be mixedCase
109
- "PERF", # Perflint
110
- "PGH", # pygrep-hooks
111
- "PIE", # flake8-pie
112
- "PL", # pylint
113
- "PT", # flake8-pytest-style
114
- "PTH", # flake8-pathlib
115
- "PYI", # flake8-pyi
116
- "RET", # flake8-return
117
- "RSE", # flake8-raise
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", # Use of exec detected
142
- "S103", # bad-file-permissions
143
- "S108", # hardcoded-temp-file
144
- "S306", # suspicious-mktemp-usage
145
- "S307", # suspicious-eval-usage
146
- "S313", # suspicious-xmlc-element-tree-usage
147
- "S314", # suspicious-xml-element-tree-usage
148
- "S315", # suspicious-xml-expat-reader-usage
149
- "S316", # suspicious-xml-expat-builder-usage
150
- "S317", # suspicious-xml-sax-usage
151
- "S318", # suspicious-xml-mini-dom-usage
152
- "S319", # suspicious-xml-pull-dom-usage
153
- "S601", # paramiko-call
154
- "S602", # subprocess-popen-with-shell-equals-true
155
- "S604", # call-with-shell-equals-true
156
- "S608", # hardcoded-sql-expression
157
- "S609", # unix-command-wildcard-injection
158
- "SIM", # flake8-simplify
159
- "SLF", # flake8-self
160
- "SLOT", # flake8-slots
161
- "T100", # Trace found: {name} used
162
- "T20", # flake8-print
163
- "TC", # flake8-type-checking
164
- "TID", # Tidy imports
165
- "TRY", # tryceratops
166
- "UP", # pyupgrade
167
- "UP031", # Use format specifiers instead of percent format
168
- "UP032", # Use f-string instead of `format` call
169
- "W", # pycodestyle
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
- "D202", # No blank lines allowed after function docstring
174
- "D203", # 1 blank line required before class docstring
175
- "D213", # Multi-line docstring summary should start at the second line
176
- "D406", # Section name should end with a newline
177
- "D407", # Section name underlining
178
- "E501", # line too long
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", # pytest.raises({exception}) is too broad, set the `match` parameter or use a more specific exception
188
- "PT018", # Assertion should be broken down into multiple parts
189
- # "RUF001", # String contains ambiguous unicode character.
190
- # "RUF002", # Docstring contains ambiguous unicode character.
191
- # "RUF003", # Comment contains ambiguous unicode character.
192
- # "RUF015", # Prefer next(...) over single element slice
193
- "SIM102", # Use a single if statement instead of nested if statements
194
- # "SIM103", # Return the condition {condition} directly
195
- # "SIM108", # Use ternary operator {contents} instead of if-else-block
196
- # "SIM115", # Use context handler for opening files
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][:-4]
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
- def test_bms_cls_none() -> None:
64
- """Test that a BMS class is correctly returned from its name."""
65
- # strip _bms to get only type
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