pypck 0.8.8__tar.gz → 0.8.10__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 (27) hide show
  1. {pypck-0.8.8/pypck.egg-info → pypck-0.8.10}/PKG-INFO +1 -1
  2. pypck-0.8.10/VERSION +1 -0
  3. {pypck-0.8.8 → pypck-0.8.10}/pypck/connection.py +4 -4
  4. {pypck-0.8.8 → pypck-0.8.10}/pypck/helpers.py +3 -3
  5. {pypck-0.8.8 → pypck-0.8.10}/pypck/lcn_defs.py +46 -44
  6. {pypck-0.8.8 → pypck-0.8.10}/pypck/module.py +5 -2
  7. {pypck-0.8.8 → pypck-0.8.10}/pypck/pck_commands.py +4 -2
  8. {pypck-0.8.8 → pypck-0.8.10}/pypck/request_handlers.py +2 -1
  9. {pypck-0.8.8 → pypck-0.8.10/pypck.egg-info}/PKG-INFO +1 -1
  10. {pypck-0.8.8 → pypck-0.8.10}/tests/test_commands.py +24 -16
  11. {pypck-0.8.8 → pypck-0.8.10}/tests/test_connection.py +76 -25
  12. {pypck-0.8.8 → pypck-0.8.10}/tests/test_dyn_text.py +10 -3
  13. {pypck-0.8.8 → pypck-0.8.10}/tests/test_messages.py +6 -1
  14. {pypck-0.8.8 → pypck-0.8.10}/tests/test_vars.py +4 -2
  15. pypck-0.8.8/VERSION +0 -1
  16. {pypck-0.8.8 → pypck-0.8.10}/LICENSE +0 -0
  17. {pypck-0.8.8 → pypck-0.8.10}/README.md +0 -0
  18. {pypck-0.8.8 → pypck-0.8.10}/pypck/__init__.py +0 -0
  19. {pypck-0.8.8 → pypck-0.8.10}/pypck/inputs.py +0 -0
  20. {pypck-0.8.8 → pypck-0.8.10}/pypck/lcn_addr.py +0 -0
  21. {pypck-0.8.8 → pypck-0.8.10}/pypck/timeout_retry.py +0 -0
  22. {pypck-0.8.8 → pypck-0.8.10}/pypck.egg-info/SOURCES.txt +0 -0
  23. {pypck-0.8.8 → pypck-0.8.10}/pypck.egg-info/dependency_links.txt +0 -0
  24. {pypck-0.8.8 → pypck-0.8.10}/pypck.egg-info/not-zip-safe +0 -0
  25. {pypck-0.8.8 → pypck-0.8.10}/pypck.egg-info/top_level.txt +0 -0
  26. {pypck-0.8.8 → pypck-0.8.10}/pyproject.toml +0 -0
  27. {pypck-0.8.8 → pypck-0.8.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypck
3
- Version: 0.8.8
3
+ Version: 0.8.10
4
4
  Summary: LCN-PCK library
5
5
  Home-page: https://github.com/alengwenus/pypck
6
6
  Author-email: Andre Lengwenus <alengwenus@gmail.com>
pypck-0.8.10/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.10
@@ -13,7 +13,7 @@ from pypck import inputs, lcn_defs
13
13
  from pypck.helpers import TaskRegistry
14
14
  from pypck.lcn_addr import LcnAddr
15
15
  from pypck.lcn_defs import LcnEvent
16
- from pypck.module import AbstractConnection, GroupConnection, ModuleConnection
16
+ from pypck.module import GroupConnection, ModuleConnection
17
17
  from pypck.pck_commands import PckGenerator
18
18
 
19
19
  _LOGGER = logging.getLogger(__name__)
@@ -243,7 +243,7 @@ class PchkConnectionManager:
243
243
  if isinstance(exc, (ConnectionRefusedError, OSError)):
244
244
  raise PchkConnectionRefusedError()
245
245
  else:
246
- raise awaitable.exception() # type: ignore
246
+ raise exc
247
247
 
248
248
  if pending:
249
249
  for awaitable in pending:
@@ -405,8 +405,8 @@ class PchkConnectionManager:
405
405
 
406
406
  def get_address_conn(
407
407
  self, addr: LcnAddr, request_serials: bool = True
408
- ) -> AbstractConnection:
409
- """Create and/or return an AbstractConnection to the given module or group."""
408
+ ) -> ModuleConnection | GroupConnection:
409
+ """Create and/or return a connection to the given module or group."""
410
410
  if addr.is_group:
411
411
  return self.get_group_conn(addr)
412
412
  return self.get_module_conn(addr, request_serials)
@@ -1,7 +1,7 @@
1
1
  """Helper functions for pypck."""
2
2
 
3
3
  import asyncio
4
- from collections.abc import Awaitable
4
+ from collections.abc import Coroutine
5
5
  from typing import Any
6
6
 
7
7
 
@@ -30,9 +30,9 @@ class TaskRegistry:
30
30
  if task in self.tasks:
31
31
  self.tasks.remove(task)
32
32
 
33
- def create_task(self, coro: Awaitable[Any]) -> "asyncio.Task[None]":
33
+ def create_task(self, coro: Coroutine[Any, Any, Any]) -> "asyncio.Task[None]":
34
34
  """Create a task and store a reference in the task registry."""
35
- task = asyncio.create_task(coro) # type: ignore
35
+ task: asyncio.Task[Any] = asyncio.create_task(coro)
36
36
  task.add_done_callback(self.remove_task)
37
37
  self.tasks.append(task)
38
38
  return task
@@ -360,6 +360,44 @@ class Var(Enum):
360
360
  S0INPUT3 = auto()
361
361
  S0INPUT4 = auto() # LCN-BU4LJVarValue
362
362
 
363
+ @classmethod
364
+ def variables(cls) -> list[Var]:
365
+ """Return a list of all variable types."""
366
+ return [
367
+ cls.VAR1ORTVAR,
368
+ cls.VAR2ORR1VAR,
369
+ cls.VAR3ORR2VAR,
370
+ cls.VAR4,
371
+ cls.VAR5,
372
+ cls.VAR6,
373
+ cls.VAR7,
374
+ cls.VAR8,
375
+ cls.VAR9,
376
+ cls.VAR10,
377
+ cls.VAR11,
378
+ cls.VAR12,
379
+ ]
380
+
381
+ @classmethod
382
+ def set_points(cls) -> list[Var]:
383
+ """Return a list of all set-point variable types."""
384
+ return [cls.R1VARSETPOINT, cls.R2VARSETPOINT]
385
+
386
+ @classmethod
387
+ def thresholds(cls) -> list[list[Var]]:
388
+ """Return a list of all threshold variable types."""
389
+ return [
390
+ [cls.THRS1, cls.THRS2, cls.THRS3, cls.THRS4, cls.THRS5],
391
+ [cls.THRS2_1, cls.THRS2_2, cls.THRS2_3, cls.THRS2_4],
392
+ [cls.THRS3_1, cls.THRS3_2, cls.THRS3_3, cls.THRS3_4],
393
+ [cls.THRS4_1, cls.THRS4_2, cls.THRS4_3, cls.THRS4_4],
394
+ ]
395
+
396
+ @classmethod
397
+ def s0s(cls) -> list[Var]:
398
+ """Return a list of all S0-input variable types."""
399
+ return [cls.S0INPUT1, cls.S0INPUT2, cls.S0INPUT3, cls.S0INPUT4]
400
+
363
401
  @staticmethod
364
402
  def var_id_to_var(var_id: int) -> Var:
365
403
  """Translate a given id into a variable type.
@@ -369,9 +407,9 @@ class Var(Enum):
369
407
  :returns: The translated variable enum.
370
408
  :rtype: Var
371
409
  """
372
- if (var_id < 0) or (var_id >= len(Var.variables)): # type: ignore
410
+ if (var_id < 0) or (var_id >= len(Var.variables())):
373
411
  raise ValueError("Bad var_id.")
374
- return Var.variables[var_id] # type: ignore
412
+ return Var.variables()[var_id]
375
413
 
376
414
  @staticmethod
377
415
  def set_point_id_to_var(set_point_id: int) -> Var:
@@ -382,9 +420,9 @@ class Var(Enum):
382
420
  :return: The translated var
383
421
  :rtype: Var
384
422
  """
385
- if (set_point_id < 0) or (set_point_id >= len(Var.set_points)): # type: ignore
423
+ if (set_point_id < 0) or (set_point_id >= len(Var.set_points())):
386
424
  raise ValueError("Bad set_point_id.")
387
- return Var.set_points[set_point_id] # type: ignore
425
+ return Var.set_points()[set_point_id]
388
426
 
389
427
  @staticmethod
390
428
  def thrs_id_to_var(register_id: int, thrs_id: int) -> Var:
@@ -399,12 +437,12 @@ class Var(Enum):
399
437
  """
400
438
  if (
401
439
  (register_id < 0)
402
- or (register_id >= len(Var.thresholds)) # type: ignore
440
+ or (register_id >= len(Var.thresholds()))
403
441
  or (thrs_id < 0)
404
442
  or (thrs_id >= (5 if (register_id == 0) else 4))
405
443
  ):
406
444
  raise ValueError("Bad register_id and/or thrs_id.")
407
- return Var.thresholds[register_id][thrs_id] # type: ignore
445
+ return Var.thresholds()[register_id][thrs_id]
408
446
 
409
447
  @staticmethod
410
448
  def s0_id_to_var(s0_id: int) -> Var:
@@ -415,9 +453,9 @@ class Var(Enum):
415
453
  :return: The translated var
416
454
  :rtype: Var
417
455
  """
418
- if (s0_id < 0) or (s0_id >= len(Var.s0s)): # type: ignore
456
+ if (s0_id < 0) or (s0_id >= len(Var.s0s())):
419
457
  raise ValueError("Bad s0_id.")
420
- return Var.s0s[s0_id] # type: ignore
458
+ return Var.s0s()[s0_id]
421
459
 
422
460
  @staticmethod
423
461
  def to_var_id(var: Var) -> int:
@@ -658,42 +696,6 @@ class Var(Enum):
658
696
  return (not lock_state) and (software_serial < 0x170206)
659
697
 
660
698
 
661
- # Helper list to get var by numeric id.
662
- Var.variables = [ # type: ignore
663
- Var.VAR1ORTVAR,
664
- Var.VAR2ORR1VAR,
665
- Var.VAR3ORR2VAR,
666
- Var.VAR4,
667
- Var.VAR5,
668
- Var.VAR6,
669
- Var.VAR7,
670
- Var.VAR8,
671
- Var.VAR9,
672
- Var.VAR10,
673
- Var.VAR11,
674
- Var.VAR12,
675
- ]
676
-
677
- # Helper list to get set-point var by numeric id.
678
- Var.set_points = [Var.R1VARSETPOINT, Var.R2VARSETPOINT] # type: ignore
679
-
680
- # Helper list to get threshold var by numeric id.
681
- Var.thresholds = [ # type: ignore
682
- [Var.THRS1, Var.THRS2, Var.THRS3, Var.THRS4, Var.THRS5],
683
- [Var.THRS2_1, Var.THRS2_2, Var.THRS2_3, Var.THRS2_4],
684
- [Var.THRS3_1, Var.THRS3_2, Var.THRS3_3, Var.THRS3_4],
685
- [Var.THRS4_1, Var.THRS4_2, Var.THRS4_3, Var.THRS4_4],
686
- ]
687
-
688
- # Helper list to get S0-input var by numeric id.
689
- Var.s0s = [ # type: ignore
690
- Var.S0INPUT1,
691
- Var.S0INPUT2,
692
- Var.S0INPUT3,
693
- Var.S0INPUT4,
694
- ]
695
-
696
-
697
699
  class VarUnit(Enum):
698
700
  """Measurement units used with LCN variables."""
699
701
 
@@ -174,19 +174,22 @@ class AbstractConnection:
174
174
  self.wants_ack, PckGenerator.rel_output(output_id, percent)
175
175
  )
176
176
 
177
- async def toggle_output(self, output_id: int, ramp: int) -> bool:
177
+ async def toggle_output(
178
+ self, output_id: int, ramp: int, to_memory: bool = False
179
+ ) -> bool:
178
180
  """Send a command that toggles a single output-port.
179
181
 
180
182
  Toggle mode: (on->off, off->on).
181
183
 
182
184
  :param int output_id: Output id 0..3
183
185
  :param int ramp: Ramp time in milliseconds
186
+ :param bool to_memory: If True, the dimming status is stored
184
187
 
185
188
  :returns: True if command was sent successfully, False otherwise
186
189
  :rtype: bool
187
190
  """
188
191
  return await self.send_command(
189
- self.wants_ack, PckGenerator.toggle_output(output_id, ramp)
192
+ self.wants_ack, PckGenerator.toggle_output(output_id, ramp, to_memory)
190
193
  )
191
194
 
192
195
  async def toggle_all_outputs(self, ramp: int) -> bool:
@@ -471,19 +471,21 @@ class PckGenerator:
471
471
  return pck
472
472
 
473
473
  @staticmethod
474
- def toggle_output(output_id: int, ramp: int) -> str:
474
+ def toggle_output(output_id: int, ramp: int, to_memory: bool = False) -> str:
475
475
  """Generate a command that toggles a single output-port.
476
476
 
477
477
  Toggle mode: (on->off, off->on).
478
478
 
479
479
  :param int output_id: Output id 0..3
480
480
  :param int ramp: Ramp value
481
+ :param bool to_memory: If True, the dimming status is stored
482
+
481
483
  :return: The PCK command (without address header) as text
482
484
  :rtype: str
483
485
  """
484
486
  if (output_id < 0) or (output_id > 3):
485
487
  raise ValueError("Invalid output_id.")
486
- return f"A{output_id + 1}TA{ramp:03d}"
488
+ return f"A{output_id + 1}{'MT' if to_memory else 'TA'}{ramp:03d}"
487
489
 
488
490
  @staticmethod
489
491
  def toggle_all_outputs(ramp: int) -> str:
@@ -660,6 +660,7 @@ class StatusRequestsHandler:
660
660
  async def activate_all(self, activate_s0: bool = False) -> None:
661
661
  """Activate all status requests."""
662
662
  await self.addr_conn.conn.segment_scan_completed_event.wait()
663
+ var_s0s = lcn_defs.Var.s0s()
663
664
  for item in (
664
665
  list(lcn_defs.OutputPort)
665
666
  + list(lcn_defs.RelayPort)
@@ -673,7 +674,7 @@ class StatusRequestsHandler:
673
674
  if (
674
675
  (not activate_s0)
675
676
  and isinstance(item, lcn_defs.Var)
676
- and (item in lcn_defs.Var.s0s) # type: ignore
677
+ and (item in var_s0s)
677
678
  ):
678
679
  continue
679
680
  await self.activate(item)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypck
3
- Version: 0.8.8
3
+ Version: 0.8.10
4
4
  Summary: LCN-PCK library
5
5
  Home-page: https://github.com/alengwenus/pypck
6
6
  Author-email: Andre Lengwenus <alengwenus@gmail.com>
@@ -1,5 +1,7 @@
1
1
  """Tests for command generation directed at bus modules and groups."""
2
2
 
3
+ from typing import Any
4
+
3
5
  import pytest
4
6
 
5
7
  from pypck.lcn_addr import LcnAddr
@@ -24,7 +26,7 @@ from pypck.pck_commands import PckGenerator
24
26
 
25
27
  NEW_VAR_SW_AGE = 0x170206
26
28
 
27
- COMMANDS = {
29
+ COMMANDS: dict[str | bytes, Any] = {
28
30
  # Host commands
29
31
  **{
30
32
  f"^ping{counter:d}": (PckGenerator.ping, counter)
@@ -93,7 +95,7 @@ COMMANDS = {
93
95
  var,
94
96
  NEW_VAR_SW_AGE,
95
97
  )
96
- for var in Var.variables # type: ignore
98
+ for var in Var.variables()
97
99
  },
98
100
  **{
99
101
  f"MWS{Var.to_set_point_id(var) + 1:03d}": (
@@ -101,7 +103,7 @@ COMMANDS = {
101
103
  var,
102
104
  NEW_VAR_SW_AGE,
103
105
  )
104
- for var in Var.set_points # type: ignore
106
+ for var in Var.set_points()
105
107
  },
106
108
  **{
107
109
  f"MWC{Var.to_s0_id(var) + 1:03d}": (
@@ -109,7 +111,7 @@ COMMANDS = {
109
111
  var,
110
112
  NEW_VAR_SW_AGE,
111
113
  )
112
- for var in Var.s0s # type: ignore
114
+ for var in Var.s0s()
113
115
  },
114
116
  **{
115
117
  f"SE{Var.to_thrs_register_id(var) + 1:03d}": (
@@ -117,7 +119,7 @@ COMMANDS = {
117
119
  var,
118
120
  NEW_VAR_SW_AGE,
119
121
  )
120
- for reg in Var.thresholds # type: ignore
122
+ for reg in Var.thresholds()
121
123
  for var in reg
122
124
  },
123
125
  # Variable status (legacy commands)
@@ -128,7 +130,7 @@ COMMANDS = {
128
130
  "MWSB": (PckGenerator.request_var_status, Var.R2VARSETPOINT, NEW_VAR_SW_AGE - 1),
129
131
  **{
130
132
  "SL1": (PckGenerator.request_var_status, var, NEW_VAR_SW_AGE - 1)
131
- for var in Var.thresholds[0] # type: ignore
133
+ for var in Var.thresholds()[0]
132
134
  },
133
135
  # Output manipulation
134
136
  **{
@@ -165,6 +167,10 @@ COMMANDS = {
165
167
  f"A{output + 1:d}TA123": (PckGenerator.toggle_output, output, 123)
166
168
  for output in range(4)
167
169
  },
170
+ **{
171
+ f"A{output + 1:d}MT123": (PckGenerator.toggle_output, output, 123, True)
172
+ for output in range(4)
173
+ },
168
174
  "AU123": (PckGenerator.toggle_all_outputs, 123),
169
175
  # Relay state manipulation
170
176
  "R80-1U1-U0": (
@@ -301,7 +307,7 @@ COMMANDS = {
301
307
  # Variable manipulation
302
308
  **{
303
309
  f"X2{var.value | 0x40:03d}016225": (PckGenerator.update_status_var, var, 4321)
304
- for var in Var.variables # type: ignore
310
+ for var in Var.variables()
305
311
  },
306
312
  "X2030044129": (PckGenerator.var_abs, Var.R1VARSETPOINT, 4201),
307
313
  "X2030108129": (PckGenerator.var_abs, Var.R2VARSETPOINT, 4201),
@@ -310,7 +316,7 @@ COMMANDS = {
310
316
  "ZS30000": (PckGenerator.var_reset, Var.TVAR, 0x170205),
311
317
  **{
312
318
  f"Z-{var.value + 1:03d}4090": (PckGenerator.var_reset, var, 0x170206)
313
- for var in Var.variables # type: ignore
319
+ for var in Var.variables()
314
320
  },
315
321
  "ZA23423": (PckGenerator.var_rel, Var.TVAR, RelVarRef.CURRENT, 23423, 0x170205),
316
322
  "ZS23423": (PckGenerator.var_rel, Var.TVAR, RelVarRef.CURRENT, -23423, 0x170205),
@@ -322,7 +328,7 @@ COMMANDS = {
322
328
  -3000,
323
329
  0x170206,
324
330
  )
325
- for var in Var.variables # type: ignore
331
+ for var in Var.variables()
326
332
  if var != Var.TVAR
327
333
  },
328
334
  **{
@@ -333,7 +339,7 @@ COMMANDS = {
333
339
  -500,
334
340
  sw_age,
335
341
  )
336
- for nvar, var in enumerate(Var.set_points) # type: ignore
342
+ for nvar, var in enumerate(Var.set_points())
337
343
  for nref, ref in enumerate(RelVarRef)
338
344
  for sw_age in (0x170206, 0x170205)
339
345
  },
@@ -345,14 +351,14 @@ COMMANDS = {
345
351
  500,
346
352
  sw_age,
347
353
  )
348
- for nvar, var in enumerate(Var.set_points) # type: ignore
354
+ for nvar, var in enumerate(Var.set_points())
349
355
  for nref, ref in enumerate(RelVarRef)
350
356
  for sw_age in (0x170206, 0x170205)
351
357
  },
352
358
  **{
353
359
  f"SS{('R', 'E')[nref]}0500SR{r + 1}{i + 1}": (
354
360
  PckGenerator.var_rel,
355
- Var.thresholds[r][i], # type: ignore
361
+ Var.thresholds()[r][i],
356
362
  ref,
357
363
  -500,
358
364
  0x170206,
@@ -364,7 +370,7 @@ COMMANDS = {
364
370
  **{
365
371
  f"SS{('R', 'E')[nref]}0500AR{r + 1}{i + 1}": (
366
372
  PckGenerator.var_rel,
367
- Var.thresholds[r][i], # type: ignore
373
+ Var.thresholds()[r][i],
368
374
  ref,
369
375
  500,
370
376
  0x170206,
@@ -376,7 +382,7 @@ COMMANDS = {
376
382
  **{
377
383
  f"SS{('R', 'E')[nref]}0500S{1 << (4 - i):05b}": (
378
384
  PckGenerator.var_rel,
379
- Var.thresholds[0][i], # type: ignore
385
+ Var.thresholds()[0][i],
380
386
  ref,
381
387
  -500,
382
388
  0x170205,
@@ -387,7 +393,7 @@ COMMANDS = {
387
393
  **{
388
394
  f"SS{('R', 'E')[nref]}0500A{1 << (4 - i):05b}": (
389
395
  PckGenerator.var_rel,
390
- Var.thresholds[0][i], # type: ignore
396
+ Var.thresholds()[0][i],
391
397
  ref,
392
398
  500,
393
399
  0x170205,
@@ -558,6 +564,8 @@ COMMANDS = {
558
564
 
559
565
 
560
566
  @pytest.mark.parametrize("expected, command", COMMANDS.items())
561
- def test_command_generation_single_mod_noack(expected, command):
567
+ def test_command_generation_single_mod_noack(
568
+ expected: str, command: tuple[Any, ...]
569
+ ) -> None:
562
570
  """Test if InputMod parses message correctly."""
563
571
  assert expected == command[0](*command[1:])
@@ -16,22 +16,29 @@ from pypck.lcn_addr import LcnAddr
16
16
  from pypck.lcn_defs import LcnEvent
17
17
  from pypck.module import ModuleConnection
18
18
 
19
+ from .conftest import MockPchkConnectionManager
20
+ from .mock_pchk import MockPchkServer
21
+
19
22
 
20
23
  @pytest.mark.asyncio
21
- async def test_close_without_connect(pypck_client):
24
+ async def test_close_without_connect(pypck_client: MockPchkConnectionManager) -> None:
22
25
  """Test closing of PchkConnectionManager without connecting."""
23
26
  await pypck_client.async_close()
24
27
 
25
28
 
26
29
  @pytest.mark.asyncio
27
- async def test_authenticate(pchk_server, pypck_client):
30
+ async def test_authenticate(
31
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
32
+ ) -> None:
28
33
  """Test authentication procedure."""
29
34
  await pypck_client.async_connect()
30
35
  assert pypck_client.is_ready()
31
36
 
32
37
 
33
38
  @pytest.mark.asyncio
34
- async def test_port_error(pchk_server, pypck_client):
39
+ async def test_port_error(
40
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
41
+ ) -> None:
35
42
  """Test wrong port."""
36
43
  pypck_client.port = 55555
37
44
  with pytest.raises(PchkConnectionRefusedError):
@@ -39,7 +46,9 @@ async def test_port_error(pchk_server, pypck_client):
39
46
 
40
47
 
41
48
  @pytest.mark.asyncio
42
- async def test_authentication_error(pchk_server, pypck_client):
49
+ async def test_authentication_error(
50
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
51
+ ) -> None:
43
52
  """Test wrong login credentials."""
44
53
  pypck_client.password = "wrong_password"
45
54
  with pytest.raises(PchkAuthenticationError):
@@ -47,7 +56,9 @@ async def test_authentication_error(pchk_server, pypck_client):
47
56
 
48
57
 
49
58
  @pytest.mark.asyncio
50
- async def test_license_error(pchk_server, pypck_client):
59
+ async def test_license_error(
60
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
61
+ ) -> None:
51
62
  """Test license error."""
52
63
  pchk_server.set_license_error(True)
53
64
 
@@ -56,14 +67,18 @@ async def test_license_error(pchk_server, pypck_client):
56
67
 
57
68
 
58
69
  @pytest.mark.asyncio
59
- async def test_timeout_error(pchk_server, pypck_client):
70
+ async def test_timeout_error(
71
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
72
+ ) -> None:
60
73
  """Test timeout when connecting."""
61
74
  with pytest.raises(PchkConnectionFailedError):
62
75
  await pypck_client.async_connect(timeout=0)
63
76
 
64
77
 
65
78
  @pytest.mark.asyncio
66
- async def test_lcn_connected(pchk_server, pypck_client):
79
+ async def test_lcn_connected(
80
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
81
+ ) -> None:
67
82
  """Test lcn disconnected event."""
68
83
  event_callback = Mock()
69
84
  pypck_client.register_for_events(event_callback)
@@ -80,7 +95,9 @@ async def test_lcn_connected(pchk_server, pypck_client):
80
95
 
81
96
 
82
97
  @pytest.mark.asyncio
83
- async def test_lcn_disconnected(pchk_server, pypck_client):
98
+ async def test_lcn_disconnected(
99
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
100
+ ) -> None:
84
101
  """Test lcn disconnected event."""
85
102
  event_callback = Mock()
86
103
  pypck_client.register_for_events(event_callback)
@@ -94,7 +111,9 @@ async def test_lcn_disconnected(pchk_server, pypck_client):
94
111
 
95
112
 
96
113
  @pytest.mark.asyncio
97
- async def test_connection_lost(pchk_server, pypck_client):
114
+ async def test_connection_lost(
115
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
116
+ ) -> None:
98
117
  """Test pchk server connection close."""
99
118
  event_callback = Mock()
100
119
  pypck_client.register_for_events(event_callback)
@@ -109,8 +128,11 @@ async def test_connection_lost(pchk_server, pypck_client):
109
128
 
110
129
  @pytest.mark.asyncio
111
130
  async def test_multiple_connections(
112
- pchk_server, pypck_client, pchk_server_2, pypck_client_2
113
- ):
131
+ pchk_server: MockPchkServer,
132
+ pypck_client: MockPchkConnectionManager,
133
+ pchk_server_2: MockPchkServer,
134
+ pypck_client_2: MockPchkConnectionManager,
135
+ ) -> None:
114
136
  """Test that two independent connections can coexists."""
115
137
  await pypck_client_2.async_connect()
116
138
 
@@ -128,7 +150,9 @@ async def test_multiple_connections(
128
150
 
129
151
 
130
152
  @pytest.mark.asyncio
131
- async def test_segment_coupler_search(pchk_server, pypck_client):
153
+ async def test_segment_coupler_search(
154
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
155
+ ) -> None:
132
156
  """Test segment coupler search."""
133
157
  await pypck_client.async_connect()
134
158
  await pypck_client.scan_segment_couplers(3, 0)
@@ -141,7 +165,9 @@ async def test_segment_coupler_search(pchk_server, pypck_client):
141
165
 
142
166
 
143
167
  @pytest.mark.asyncio
144
- async def test_segment_coupler_response(pchk_server, pypck_client):
168
+ async def test_segment_coupler_response(
169
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
170
+ ) -> None:
145
171
  """Test segment coupler response."""
146
172
  await pypck_client.async_connect()
147
173
 
@@ -159,7 +185,9 @@ async def test_segment_coupler_response(pchk_server, pypck_client):
159
185
 
160
186
 
161
187
  @pytest.mark.asyncio
162
- async def test_module_scan(pchk_server, pypck_client):
188
+ async def test_module_scan(
189
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
190
+ ) -> None:
163
191
  """Test module scan."""
164
192
  await pypck_client.async_connect()
165
193
  await pypck_client.scan_modules(3, 0)
@@ -170,7 +198,9 @@ async def test_module_scan(pchk_server, pypck_client):
170
198
 
171
199
 
172
200
  @pytest.mark.asyncio
173
- async def test_module_sn_response(pchk_server, pypck_client):
201
+ async def test_module_sn_response(
202
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
203
+ ) -> None:
174
204
  """Test module scan."""
175
205
  await pypck_client.async_connect()
176
206
  module = pypck_client.get_address_conn(LcnAddr(0, 7, False))
@@ -187,7 +217,9 @@ async def test_module_sn_response(pchk_server, pypck_client):
187
217
 
188
218
 
189
219
  @pytest.mark.asyncio
190
- async def test_send_command_to_server(pchk_server, pypck_client):
220
+ async def test_send_command_to_server(
221
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
222
+ ) -> None:
191
223
  """Test sending a command to the PCHK server."""
192
224
  await pypck_client.async_connect()
193
225
  message = ">M000007.PIN003"
@@ -196,14 +228,16 @@ async def test_send_command_to_server(pchk_server, pypck_client):
196
228
 
197
229
 
198
230
  @pytest.mark.asyncio
199
- async def test_ping(pchk_server, pypck_client):
231
+ async def test_ping(
232
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
233
+ ) -> None:
200
234
  """Test if pings are send."""
201
235
  await pypck_client.async_connect()
202
236
  assert await pchk_server.received("^ping0")
203
237
 
204
238
 
205
239
  @pytest.mark.asyncio
206
- async def test_add_address_connections(pypck_client):
240
+ async def test_add_address_connections(pypck_client: MockPchkConnectionManager) -> None:
207
241
  """Test if new address connections are added on request."""
208
242
  lcn_addr = LcnAddr(0, 10, False)
209
243
  assert lcn_addr not in pypck_client.address_conns
@@ -215,7 +249,9 @@ async def test_add_address_connections(pypck_client):
215
249
 
216
250
 
217
251
  @pytest.mark.asyncio
218
- async def test_add_address_connections_by_message(pchk_server, pypck_client):
252
+ async def test_add_address_connections_by_message(
253
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
254
+ ) -> None:
219
255
  """Test if new address connections are added by received message."""
220
256
  await pypck_client.async_connect()
221
257
  lcn_addr = LcnAddr(0, 10, False)
@@ -229,10 +265,13 @@ async def test_add_address_connections_by_message(pchk_server, pypck_client):
229
265
 
230
266
 
231
267
  @pytest.mark.asyncio
232
- async def test_groups_static_membership_discovery(pchk_server, pypck_client):
268
+ async def test_groups_static_membership_discovery(
269
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
270
+ ) -> None:
233
271
  """Test module scan."""
234
272
  await pypck_client.async_connect()
235
273
  module = pypck_client.get_address_conn(LcnAddr(0, 10, False))
274
+ assert isinstance(module, ModuleConnection)
236
275
 
237
276
  task = asyncio.create_task(module.request_static_groups())
238
277
  assert await pchk_server.received(">M000010.GP")
@@ -245,10 +284,13 @@ async def test_groups_static_membership_discovery(pchk_server, pypck_client):
245
284
 
246
285
 
247
286
  @pytest.mark.asyncio
248
- async def test_groups_dynamic_membership_discovery(pchk_server, pypck_client):
287
+ async def test_groups_dynamic_membership_discovery(
288
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
289
+ ) -> None:
249
290
  """Test module scan."""
250
291
  await pypck_client.async_connect()
251
292
  module = pypck_client.get_address_conn(LcnAddr(0, 10, False))
293
+ assert isinstance(module, ModuleConnection)
252
294
 
253
295
  task = asyncio.create_task(module.request_dynamic_groups())
254
296
  assert await pchk_server.received(">M000010.GD")
@@ -261,10 +303,13 @@ async def test_groups_dynamic_membership_discovery(pchk_server, pypck_client):
261
303
 
262
304
 
263
305
  @pytest.mark.asyncio
264
- async def test_groups_membership_discovery(pchk_server, pypck_client):
306
+ async def test_groups_membership_discovery(
307
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
308
+ ) -> None:
265
309
  """Test module scan."""
266
310
  await pypck_client.async_connect()
267
311
  module = pypck_client.get_address_conn(LcnAddr(0, 10, False))
312
+ assert isinstance(module, ModuleConnection)
268
313
 
269
314
  task = asyncio.create_task(module.request_groups())
270
315
  assert await pchk_server.received(">M000010.GP")
@@ -282,7 +327,9 @@ async def test_groups_membership_discovery(pchk_server, pypck_client):
282
327
 
283
328
 
284
329
  @pytest.mark.asyncio
285
- async def test_multiple_serial_requests(pchk_server, pypck_client):
330
+ async def test_multiple_serial_requests(
331
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
332
+ ) -> None:
286
333
  """Test module scan."""
287
334
  await pypck_client.async_connect()
288
335
 
@@ -302,7 +349,9 @@ async def test_multiple_serial_requests(pchk_server, pypck_client):
302
349
 
303
350
 
304
351
  @pytest.mark.asyncio
305
- async def test_dump_modules_no_segement_couplers(pchk_server, pypck_client):
352
+ async def test_dump_modules_no_segement_couplers(
353
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
354
+ ) -> None:
306
355
  """Test module information dumping."""
307
356
  await pypck_client.async_connect()
308
357
 
@@ -359,7 +408,9 @@ async def test_dump_modules_no_segement_couplers(pchk_server, pypck_client):
359
408
 
360
409
 
361
410
  @pytest.mark.asyncio
362
- async def test_dump_modules_multi_segment(pchk_server, pypck_client):
411
+ async def test_dump_modules_multi_segment(
412
+ pchk_server: MockPchkServer, pypck_client: MockPchkConnectionManager
413
+ ) -> None:
363
414
  """Test module information dumping."""
364
415
  await pypck_client.async_connect()
365
416
 
@@ -3,9 +3,12 @@
3
3
  from unittest.mock import patch
4
4
 
5
5
  import pytest
6
+
6
7
  from pypck.lcn_addr import LcnAddr
7
8
  from pypck.module import ModuleConnection
8
9
 
10
+ from .conftest import MockPchkConnectionManager
11
+
9
12
  TEST_VECTORS = {
10
13
  # empty
11
14
  "": (b"", b"", b"", b"", b""),
@@ -57,8 +60,12 @@ TEST_VECTORS = {
57
60
 
58
61
  @pytest.mark.asyncio
59
62
  @pytest.mark.parametrize("text, parts", TEST_VECTORS.items())
60
- async def test_dyn_text(pypck_client, text, parts):
61
- """dyn_text."""
63
+ async def test_dyn_text(
64
+ pypck_client: MockPchkConnectionManager,
65
+ text: str,
66
+ parts: tuple[bytes, bytes, bytes, bytes, bytes],
67
+ ) -> None:
68
+ """Tests for dynamic text."""
62
69
  # await pypck_client.async_connect()
63
70
  module = pypck_client.get_address_conn(LcnAddr(0, 10, False))
64
71
 
@@ -70,4 +77,4 @@ async def test_dyn_text(pypck_client, text, parts):
70
77
  _, commands = zip(*await_args)
71
78
 
72
79
  for i, part in enumerate(parts):
73
- assert f"GTDT4{i+1:d}".encode() + part in commands
80
+ assert f"GTDT4{i + 1:d}".encode() + part in commands
@@ -1,5 +1,7 @@
1
1
  """Tests for input message parsing for bus messages."""
2
2
 
3
+ from typing import Any
4
+
3
5
  import pytest
4
6
 
5
7
  from pypck.inputs import (
@@ -348,7 +350,10 @@ MESSAGES = {
348
350
 
349
351
 
350
352
  @pytest.mark.parametrize("message, expected", MESSAGES.items())
351
- def test_message_parsing_mod_inputs(message, expected):
353
+ def test_message_parsing_mod_inputs(
354
+ message: str,
355
+ expected: list[tuple[Any, ...]],
356
+ ) -> None:
352
357
  """Test if InputMod parses message correctly."""
353
358
  inputs = InputParser.parse(message)
354
359
  assert len(inputs) == len(expected)
@@ -1,7 +1,9 @@
1
1
  """Tests for variable value and unit handling."""
2
2
 
3
3
  import math
4
+
4
5
  import pytest
6
+
5
7
  from pypck.lcn_defs import VarUnit, VarValue
6
8
 
7
9
  VARIABLE_TEST_VALUES = (
@@ -108,7 +110,7 @@ CALIBRATION_TEST_VECTORS = (
108
110
 
109
111
 
110
112
  @pytest.mark.parametrize("unit, native, expected", ROUNDTRIP_TEST_VECTORS)
111
- def test_roundtrip(unit, native, expected):
113
+ def test_roundtrip(unit: VarUnit, native: int, expected: VarValue) -> None:
112
114
  """Test that variable conversion roundtrips."""
113
115
  assert (
114
116
  expected
@@ -119,6 +121,6 @@ def test_roundtrip(unit, native, expected):
119
121
 
120
122
 
121
123
  @pytest.mark.parametrize("unit, native, value", CALIBRATION_TEST_VECTORS)
122
- def test_calibration(unit, native, value):
124
+ def test_calibration(unit: VarUnit, native: int, value: int | float) -> None:
123
125
  """Test proper calibration of variable conversion."""
124
126
  assert value == VarValue.to_var_unit(VarValue.from_native(native), unit)
pypck-0.8.8/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.8.8
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