aiohomematic 2025.10.2__tar.gz → 2025.10.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.

Potentially problematic release.


This version of aiohomematic might be problematic. Click here for more details.

Files changed (107) hide show
  1. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/PKG-INFO +1 -1
  2. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/async_support.py +1 -1
  3. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/central/__init__.py +1 -1
  4. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/central/xml_rpc_server.py +6 -1
  5. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/const.py +1 -1
  6. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/siren.py +2 -0
  7. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/data_point.py +1 -0
  8. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/data_point.py +1 -1
  9. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/support.py +2 -2
  10. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/property_decorators.py +2 -0
  11. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic.egg-info/PKG-INFO +1 -1
  12. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic.egg-info/SOURCES.txt +1 -0
  13. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic_support/client_local.py +7 -2
  14. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_central.py +21 -9
  15. aiohomematic-2025.10.3/tests/test_kwonly_lint.py +29 -0
  16. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/LICENSE +0 -0
  17. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/README.md +0 -0
  18. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/__init__.py +0 -0
  19. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/caches/__init__.py +0 -0
  20. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/caches/dynamic.py +0 -0
  21. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/caches/persistent.py +0 -0
  22. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/caches/visibility.py +0 -0
  23. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/central/decorators.py +0 -0
  24. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/client/__init__.py +0 -0
  25. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/client/_rpc_errors.py +0 -0
  26. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/client/json_rpc.py +0 -0
  27. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/client/xml_rpc.py +0 -0
  28. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/context.py +0 -0
  29. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/converter.py +0 -0
  30. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/decorators.py +0 -0
  31. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/exceptions.py +0 -0
  32. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/hmcli.py +0 -0
  33. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/__init__.py +0 -0
  34. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/calculated/__init__.py +0 -0
  35. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/calculated/climate.py +0 -0
  36. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/calculated/data_point.py +0 -0
  37. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/calculated/operating_voltage_level.py +0 -0
  38. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/calculated/support.py +0 -0
  39. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/__init__.py +0 -0
  40. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/climate.py +0 -0
  41. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/const.py +0 -0
  42. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/cover.py +0 -0
  43. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/data_point.py +0 -0
  44. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/definition.py +0 -0
  45. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/light.py +0 -0
  46. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/lock.py +0 -0
  47. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/support.py +0 -0
  48. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/switch.py +0 -0
  49. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/custom/valve.py +0 -0
  50. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/device.py +0 -0
  51. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/event.py +0 -0
  52. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/__init__.py +0 -0
  53. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/action.py +0 -0
  54. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/binary_sensor.py +0 -0
  55. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/button.py +0 -0
  56. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/number.py +0 -0
  57. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/select.py +0 -0
  58. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/sensor.py +0 -0
  59. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/switch.py +0 -0
  60. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/generic/text.py +0 -0
  61. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/__init__.py +0 -0
  62. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/binary_sensor.py +0 -0
  63. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/button.py +0 -0
  64. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/data_point.py +0 -0
  65. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/number.py +0 -0
  66. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/select.py +0 -0
  67. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/sensor.py +0 -0
  68. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/switch.py +0 -0
  69. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/hub/text.py +0 -0
  70. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/model/update.py +0 -0
  71. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/py.typed +0 -0
  72. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/fetch_all_device_data.fn +0 -0
  73. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/get_program_descriptions.fn +0 -0
  74. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/get_serial.fn +0 -0
  75. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/get_system_variable_descriptions.fn +0 -0
  76. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/set_program_state.fn +0 -0
  77. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/rega_scripts/set_system_variable.fn +0 -0
  78. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/support.py +0 -0
  79. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic/validator.py +0 -0
  80. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic.egg-info/dependency_links.txt +0 -0
  81. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic.egg-info/requires.txt +0 -0
  82. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic.egg-info/top_level.txt +0 -0
  83. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/aiohomematic_support/__init__.py +0 -0
  84. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/pyproject.toml +0 -0
  85. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/setup.cfg +0 -0
  86. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_action.py +0 -0
  87. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_binary_sensor.py +0 -0
  88. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_button.py +0 -0
  89. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_calculated_support.py +0 -0
  90. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_central_pydevccu.py +0 -0
  91. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_climate.py +0 -0
  92. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_cover.py +0 -0
  93. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_decorator.py +0 -0
  94. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_device.py +0 -0
  95. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_entity.py +0 -0
  96. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_event.py +0 -0
  97. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_json_rpc.py +0 -0
  98. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_light.py +0 -0
  99. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_lock.py +0 -0
  100. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_number.py +0 -0
  101. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_select.py +0 -0
  102. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_sensor.py +0 -0
  103. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_siren.py +0 -0
  104. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_support.py +0 -0
  105. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_switch.py +0 -0
  106. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_text.py +0 -0
  107. {aiohomematic-2025.10.2 → aiohomematic-2025.10.3}/tests/test_valve.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiohomematic
3
- Version: 2025.10.2
3
+ Version: 2025.10.3
4
4
  Summary: Homematic interface for Home Assistant running on Python 3.
5
5
  Home-page: https://github.com/sukramj/aiohomematic
6
6
  Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
@@ -85,7 +85,7 @@ class Looper:
85
85
  )
86
86
  return
87
87
 
88
- def _async_create_task[R](self, target: Coroutine[Any, Any, R], name: str) -> asyncio.Task[R]:
88
+ def _async_create_task[R](self, target: Coroutine[Any, Any, R], name: str) -> asyncio.Task[R]: # kwonly: disable
89
89
  """Create a task from within the event_loop. This method must be run in the event_loop."""
90
90
  task = self._loop.create_task(target, name=name)
91
91
  self._tasks.add(task)
@@ -1640,7 +1640,7 @@ class _Scheduler(threading.Thread):
1640
1640
  ),
1641
1641
  ]
1642
1642
 
1643
- def _backend_system_callback(self, system_event: BackendSystemEvent, **kwargs: Any) -> None:
1643
+ def _backend_system_callback(self, *, system_event: BackendSystemEvent, **kwargs: Any) -> None:
1644
1644
  """Handle event of new device creation, to delay the start of the sysvar scan."""
1645
1645
  if system_event == BackendSystemEvent.DEVICES_CREATED:
1646
1646
  self._devices_created = True
@@ -27,6 +27,9 @@ _LOGGER: Final = logging.getLogger(__name__)
27
27
  class RPCFunctions:
28
28
  """The XML-RPC functions the backend will expect."""
29
29
 
30
+ # Disable kw-only linter for this class since XML-RPC signatures are positional by protocol
31
+ __kwonly_check__ = False
32
+
30
33
  def __init__(self, *, xml_rpc_server: XmlRpcServer) -> None:
31
34
  """Init RPCFunctions."""
32
35
  self._xml_rpc_server: Final = xml_rpc_server
@@ -161,6 +164,8 @@ class AioHomematicXMLRPCServer(SimpleXMLRPCServer):
161
164
  system_listMethods(self, interface_id: str.
162
165
  """
163
166
 
167
+ __kwonly_check__ = False
168
+
164
169
  def system_listMethods(self, interface_id: str | None = None, /) -> list[str]:
165
170
  """Return a list of the methods supported by the server."""
166
171
  return SimpleXMLRPCServer.system_listMethods(self)
@@ -198,7 +203,7 @@ class XmlRpcServer(threading.Thread):
198
203
  self._simple_xml_rpc_server.register_instance(RPCFunctions(xml_rpc_server=self), allow_dotted_names=True)
199
204
  self._centrals: Final[dict[str, hmcu.CentralUnit]] = {}
200
205
 
201
- def __new__(cls, ip_addr: str, port: int) -> XmlRpcServer: # noqa: PYI034
206
+ def __new__(cls, ip_addr: str, port: int) -> XmlRpcServer: # noqa: PYI034 # kwonly: disable
202
207
  """Create new XmlRPC server."""
203
208
  if (xml_rpc := cls._instances.get((ip_addr, port))) is None:
204
209
  _LOGGER.debug("Creating XmlRpc server")
@@ -19,7 +19,7 @@ import sys
19
19
  from types import MappingProxyType
20
20
  from typing import Any, Final, NamedTuple, Required, TypeAlias, TypedDict
21
21
 
22
- VERSION: Final = "2025.10.2"
22
+ VERSION: Final = "2025.10.3"
23
23
 
24
24
  # Detect test speedup mode via environment
25
25
  _TEST_SPEEDUP: Final = (
@@ -79,6 +79,7 @@ class BaseCustomDpSiren(CustomDataPoint):
79
79
  @bind_collector()
80
80
  async def turn_on(
81
81
  self,
82
+ *,
82
83
  collector: CallParameterCollector | None = None,
83
84
  **kwargs: Unpack[SirenOnArgs],
84
85
  ) -> None:
@@ -143,6 +144,7 @@ class CustomDpIpSiren(BaseCustomDpSiren):
143
144
  @bind_collector()
144
145
  async def turn_on(
145
146
  self,
147
+ *,
146
148
  collector: CallParameterCollector | None = None,
147
149
  **kwargs: Unpack[SirenOnArgs],
148
150
  ) -> None:
@@ -999,6 +999,7 @@ class CallParameterCollector:
999
999
 
1000
1000
  def add_data_point(
1001
1001
  self,
1002
+ *,
1002
1003
  data_point: BaseParameterDataPoint,
1003
1004
  value: Any,
1004
1005
  collector_order: int,
@@ -111,7 +111,7 @@ class GenericDataPoint[ParameterT: GenericParameterType, InputParameterT: Generi
111
111
  converted_value = self._convert_value(value=prepared_value)
112
112
  # if collector is set, then add value to collector
113
113
  if collector:
114
- collector.add_data_point(self, value=converted_value, collector_order=collector_order)
114
+ collector.add_data_point(data_point=self, value=converted_value, collector_order=collector_order)
115
115
  return set()
116
116
 
117
117
  # if collector is not set, then send value directly
@@ -87,7 +87,7 @@ class ChannelNameData:
87
87
  return ChannelNameData(device_name="", channel_name="")
88
88
 
89
89
  @staticmethod
90
- def _get_channel_name(device_name: str, channel_name: str) -> str:
90
+ def _get_channel_name(*, device_name: str, channel_name: str) -> str:
91
91
  """Return the channel_name of the data_point only name."""
92
92
  if device_name and channel_name and channel_name.startswith(device_name):
93
93
  c_name = channel_name.replace(device_name, "").strip()
@@ -121,7 +121,7 @@ class DataPointNameData(ChannelNameData):
121
121
  return DataPointNameData(device_name="", channel_name="")
122
122
 
123
123
  @staticmethod
124
- def _get_channel_parameter_name(channel_name: str, parameter_name: str | None) -> str:
124
+ def _get_channel_parameter_name(*, channel_name: str, parameter_name: str | None) -> str:
125
125
  """Return the channel parameter name of the data_point."""
126
126
  if channel_name and parameter_name:
127
127
  return f"{channel_name} {parameter_name}".strip()
@@ -65,6 +65,8 @@ class _GenericProperty[GETTER, SETTER](property):
65
65
 
66
66
  """
67
67
 
68
+ __kwonly_check__ = False
69
+
68
70
  fget: Callable[[Any], GETTER] | None
69
71
  fset: Callable[[Any, SETTER], None] | None
70
72
  fdel: Callable[[Any], None] | None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiohomematic
3
- Version: 2025.10.2
3
+ Version: 2025.10.3
4
4
  Summary: Homematic interface for Home Assistant running on Python 3.
5
5
  Home-page: https://github.com/sukramj/aiohomematic
6
6
  Author-email: SukramJ <sukramj@icloud.com>, Daniel Perna <danielperna84@gmail.com>
@@ -93,6 +93,7 @@ tests/test_device.py
93
93
  tests/test_entity.py
94
94
  tests/test_event.py
95
95
  tests/test_json_rpc.py
96
+ tests/test_kwonly_lint.py
96
97
  tests/test_light.py
97
98
  tests/test_lock.py
98
99
  tests/test_number.py
@@ -153,7 +153,7 @@ class ClientLocal(Client): # pragma: no cover
153
153
 
154
154
  @inspector(re_raise=False)
155
155
  async def get_all_system_variables(
156
- self, markers: tuple[DescriptionMarker | str, ...]
156
+ self, *, markers: tuple[DescriptionMarker | str, ...]
157
157
  ) -> tuple[SystemVariableData, ...]:
158
158
  """Get all system variables from the backend."""
159
159
  return ()
@@ -203,6 +203,7 @@ class ClientLocal(Client): # pragma: no cover
203
203
  @inspector(log_level=logging.NOTSET)
204
204
  async def get_value(
205
205
  self,
206
+ *,
206
207
  channel_address: str,
207
208
  paramset_key: ParamsetKey,
208
209
  parameter: str,
@@ -214,6 +215,7 @@ class ClientLocal(Client): # pragma: no cover
214
215
  @inspector(re_raise=False, no_raise_return=set())
215
216
  async def set_value(
216
217
  self,
218
+ *,
217
219
  channel_address: str,
218
220
  paramset_key: ParamsetKey,
219
221
  parameter: str,
@@ -236,6 +238,7 @@ class ClientLocal(Client): # pragma: no cover
236
238
  @inspector
237
239
  async def get_paramset(
238
240
  self,
241
+ *,
239
242
  address: str,
240
243
  paramset_key: ParamsetKey | str,
241
244
  call_source: CallSource = CallSource.MANUAL_OR_SCHEDULED,
@@ -249,7 +252,7 @@ class ClientLocal(Client): # pragma: no cover
249
252
  return {}
250
253
 
251
254
  async def _get_paramset_description(
252
- self, address: str, paramset_key: ParamsetKey
255
+ self, *, address: str, paramset_key: ParamsetKey
253
256
  ) -> dict[str, ParameterData] | None:
254
257
  """Get paramset description from the backend."""
255
258
  if not self._local_resources:
@@ -277,6 +280,7 @@ class ClientLocal(Client): # pragma: no cover
277
280
  @inspector(measure_performance=True)
278
281
  async def put_paramset(
279
282
  self,
283
+ *,
280
284
  channel_address: str,
281
285
  paramset_key_or_link_address: ParamsetKey | str,
282
286
  values: Any,
@@ -312,6 +316,7 @@ class ClientLocal(Client): # pragma: no cover
312
316
 
313
317
  async def _load_all_json_files(
314
318
  self,
319
+ *,
315
320
  anchor: str,
316
321
  resource: str,
317
322
  include_list: list[str] | None = None,
@@ -183,7 +183,9 @@ async def test_device_un_ignore_etrv(
183
183
  expected_result: bool,
184
184
  ) -> None:
185
185
  """Test device un ignore."""
186
- central, _ = await factory.get_default_central({"VCU3609622": "HmIP-eTRV-2.json"}, un_ignore_list=[line])
186
+ central, _ = await factory.get_default_central(
187
+ address_device_translation={"VCU3609622": "HmIP-eTRV-2.json"}, un_ignore_list=[line]
188
+ )
187
189
  try:
188
190
  channel = _FakeChannel(model="HmIP-eTRV-2", no=channel_no)
189
191
  assert (
@@ -221,7 +223,9 @@ async def test_device_un_ignore_broll(
221
223
  expected_result: bool,
222
224
  ) -> None:
223
225
  """Test device un ignore."""
224
- central, _ = await factory.get_default_central({"VCU8537918": "HmIP-BROLL.json"}, un_ignore_list=[line])
226
+ central, _ = await factory.get_default_central(
227
+ address_device_translation={"VCU8537918": "HmIP-BROLL.json"}, un_ignore_list=[line]
228
+ )
225
229
  try:
226
230
  channel = _FakeChannel(model="HmIP-BROLL", no=channel_no)
227
231
  assert (
@@ -262,7 +266,9 @@ async def test_device_un_ignore_hm(
262
266
  expected_result: bool,
263
267
  ) -> None:
264
268
  """Test device un ignore."""
265
- central, _ = await factory.get_default_central({"VCU0000341": "HM-TC-IT-WM-W-EU.json"}, un_ignore_list=[line])
269
+ central, _ = await factory.get_default_central(
270
+ address_device_translation={"VCU0000341": "HM-TC-IT-WM-W-EU.json"}, un_ignore_list=[line]
271
+ )
266
272
  try:
267
273
  channel = _FakeChannel(model="HM-TC-IT-WM-W-EU", no=channel_no)
268
274
  assert (
@@ -347,7 +353,9 @@ async def test_device_un_ignore_hm2(
347
353
  expected_result: bool,
348
354
  ) -> None:
349
355
  """Test device un ignore."""
350
- central, _ = await factory.get_default_central({"VCU0000137": "HM-ES-PMSw1-Pl.json"}, un_ignore_list=lines)
356
+ central, _ = await factory.get_default_central(
357
+ address_device_translation={"VCU0000137": "HM-ES-PMSw1-Pl.json"}, un_ignore_list=lines
358
+ )
351
359
  try:
352
360
  channel = _FakeChannel(model="HM-ES-PMSw1-Pl", no=channel_no)
353
361
  assert (
@@ -401,7 +409,7 @@ async def test_ignore_(
401
409
  ) -> None:
402
410
  """Test device un ignore."""
403
411
  central, _ = await factory.get_default_central(
404
- {"VCU1769958": "HmIP-BWTH.json", "VCU3609622": "HmIP-eTRV-2.json"},
412
+ address_device_translation={"VCU1769958": "HmIP-BWTH.json", "VCU3609622": "HmIP-eTRV-2.json"},
405
413
  ignore_custom_device_definition_models=ignore_custom_device_definition_models,
406
414
  )
407
415
  try:
@@ -438,7 +446,7 @@ async def test_all_parameters(
438
446
  expected_result: int,
439
447
  ) -> None:
440
448
  """Test all_parameters."""
441
- central, _ = await factory.get_default_central(TEST_DEVICES)
449
+ central, _ = await factory.get_default_central(address_device_translation=TEST_DEVICES)
442
450
  parameters = central.get_parameters(
443
451
  paramset_key=ParamsetKey.VALUES,
444
452
  operations=operations,
@@ -472,7 +480,9 @@ async def test_all_parameters_with_un_ignore(
472
480
  expected_result: int,
473
481
  ) -> None:
474
482
  """Test all_parameters."""
475
- central, _ = await factory.get_default_central(TEST_DEVICES, un_ignore_list=["ACTIVE_PROFILE"])
483
+ central, _ = await factory.get_default_central(
484
+ address_device_translation=TEST_DEVICES, un_ignore_list=["ACTIVE_PROFILE"]
485
+ )
476
486
  parameters = central.get_parameters(
477
487
  paramset_key=ParamsetKey.VALUES,
478
488
  operations=operations,
@@ -675,7 +685,7 @@ async def test_virtual_remote_delete(
675
685
  @pytest.mark.asyncio
676
686
  async def test_central_not_alive(factory: helper.Factory) -> None:
677
687
  """Test central other methods."""
678
- central, client = await factory.get_unpatched_default_central({}, do_mock_client=False)
688
+ central, client = await factory.get_unpatched_default_central(address_device_translation={}, do_mock_client=False)
679
689
  try:
680
690
  mock_client = helper.get_mock(instance=client, available=False)
681
691
  assert central.system_information.serial is None
@@ -817,7 +827,9 @@ async def test_central_services(
817
827
  @pytest.mark.asyncio
818
828
  async def test_central_direct(factory: helper.Factory) -> None:
819
829
  """Test central other methods."""
820
- central, client = await factory.get_unpatched_default_central(TEST_DEVICES, do_mock_client=False)
830
+ central, client = await factory.get_unpatched_default_central(
831
+ address_device_translation=TEST_DEVICES, do_mock_client=False
832
+ )
821
833
  try:
822
834
  mock_client = helper.get_mock(instance=client, available=False)
823
835
  assert central.system_information.serial is None
@@ -0,0 +1,29 @@
1
+ """Tests for keyword-only method linter (script.lint_kwonly)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ import script.lint_kwonly as kwlint
8
+
9
+
10
+ def test_kwonly_lint_detects_simple_init(tmp_path: Path) -> None:
11
+ """The linter must detect missing '*' for __init__ beyond the first param."""
12
+ code = "class Foo:\n def __init__(self, x):\n pass\n"
13
+ p = tmp_path / "sample.py"
14
+ p.write_text(code, encoding="utf-8")
15
+
16
+ violations = kwlint.check_file(str(p))
17
+ assert violations, "Expected at least one violation to be reported"
18
+ msgs = "\n".join(str(v) for v in violations)
19
+ assert "method '__init__'" in msgs
20
+
21
+
22
+ def test_kwonly_lint_ignores_varargs(tmp_path: Path) -> None:
23
+ """If *args is in the method signature, the linter must not flag it."""
24
+ code = "class Foo:\n def bar(self, x, *args):\n pass\n"
25
+ p = tmp_path / "sample_varargs.py"
26
+ p.write_text(code, encoding="utf-8")
27
+
28
+ violations = kwlint.check_file(str(p))
29
+ assert not violations, f"Did not expect violations, got: {[str(v) for v in violations]}"