pypck 0.9.7__py3-none-any.whl → 0.9.9__py3-none-any.whl

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.
pypck/device.py CHANGED
@@ -50,8 +50,6 @@ class DeviceConnection:
50
50
  self._serials_known = asyncio.Event()
51
51
 
52
52
  self.input_callbacks: set[Callable[[inputs.Input], None]] = set()
53
- self.last_requested_var_without_type_in_response = lcn_defs.Var.UNKNOWN
54
- self.last_var_lock = asyncio.Lock()
55
53
 
56
54
  # List of queued acknowledge codes from the LCN modules.
57
55
  self.acknowledges: asyncio.Queue[lcn_defs.AcknowledgeErrorCode] = (
@@ -60,6 +58,7 @@ class DeviceConnection:
60
58
 
61
59
  # StatusRequester
62
60
  self.status_requester = StatusRequester(self)
61
+ self.request_lock = asyncio.Lock()
63
62
 
64
63
  if self.addr.is_group:
65
64
  self.wants_ack = False # groups do not send acks
@@ -773,29 +772,9 @@ class DeviceConnection:
773
772
  await self.on_ack(inp.code)
774
773
  return None
775
774
 
776
- # handle typeless variable responses
777
- if isinstance(inp, inputs.ModStatusVar):
778
- inp = self.preprocess_modstatusvar(inp)
779
-
780
775
  for input_callback in self.input_callbacks:
781
776
  input_callback(inp)
782
777
 
783
- def preprocess_modstatusvar(self, inp: inputs.ModStatusVar) -> inputs.Input:
784
- """Fill typeless response with last requested variable type."""
785
- if inp.orig_var == lcn_defs.Var.UNKNOWN:
786
- # Response without type (%Msssaaa.wwwww)
787
- inp.var = self.last_requested_var_without_type_in_response
788
-
789
- self.last_requested_var_without_type_in_response = lcn_defs.Var.UNKNOWN
790
-
791
- if self.last_var_lock.locked():
792
- self.last_var_lock.release()
793
- else:
794
- # Response with variable type (%Msssaaa.Avvvwww)
795
- inp.var = inp.orig_var
796
-
797
- return inp
798
-
799
778
  async def dump_details(self) -> dict[str, Any]:
800
779
  """Dump detailed information about this module."""
801
780
  is_local_segment = self.addr.seg_id in (0, self.conn.local_seg_id)
@@ -816,11 +795,15 @@ class DeviceConnection:
816
795
  "groups": {
817
796
  "static": sorted(
818
797
  addr.addr_id
819
- for addr in await self.request_group_memberships(dynamic=False)
798
+ for addr in (
799
+ await self.request_group_memberships(dynamic=False) or set()
800
+ )
820
801
  ),
821
802
  "dynamic": sorted(
822
803
  addr.addr_id
823
- for addr in await self.request_group_memberships(dynamic=True)
804
+ for addr in (
805
+ await self.request_group_memberships(dynamic=True) or set()
806
+ )
824
807
  ),
825
808
  },
826
809
  }
@@ -844,15 +827,13 @@ class DeviceConnection:
844
827
  _LOGGER.info("Status requests are not supported for groups.")
845
828
  return None
846
829
 
847
- result = await self.status_requester.request(
830
+ return await self.status_requester.request(
848
831
  response_type=inputs.ModStatusOutput,
849
832
  request_pck=PckGenerator.request_output_status(output_id=output_port.value),
850
833
  max_age=max_age,
851
834
  output_id=output_port.value,
852
835
  )
853
836
 
854
- return cast(inputs.ModStatusOutput, result)
855
-
856
837
  async def request_status_relays(
857
838
  self, max_age: int = 0
858
839
  ) -> inputs.ModStatusRelays | None:
@@ -861,14 +842,12 @@ class DeviceConnection:
861
842
  _LOGGER.info("Status requests are not supported for groups.")
862
843
  return None
863
844
 
864
- result = await self.status_requester.request(
845
+ return await self.status_requester.request(
865
846
  response_type=inputs.ModStatusRelays,
866
847
  request_pck=PckGenerator.request_relays_status(),
867
848
  max_age=max_age,
868
849
  )
869
850
 
870
- return cast(inputs.ModStatusRelays, result)
871
-
872
851
  async def request_status_motor_position(
873
852
  self,
874
853
  motor: lcn_defs.MotorPort,
@@ -894,15 +873,13 @@ class DeviceConnection:
894
873
  _LOGGER.debug("Only BS4 mode is supported for motor position requests.")
895
874
  return None
896
875
 
897
- result = await self.status_requester.request(
876
+ return await self.status_requester.request(
898
877
  response_type=inputs.ModStatusMotorPositionBS4,
899
878
  request_pck=PckGenerator.request_motor_position_status(motor.value // 2),
900
879
  max_age=max_age,
901
880
  motor=motor.value,
902
881
  )
903
882
 
904
- return cast(inputs.ModStatusMotorPositionBS4, result)
905
-
906
883
  async def request_status_binary_sensors(
907
884
  self, max_age: int = 0
908
885
  ) -> inputs.ModStatusBinSensors | None:
@@ -911,14 +888,12 @@ class DeviceConnection:
911
888
  _LOGGER.info("Status requests are not supported for groups.")
912
889
  return None
913
890
 
914
- result = await self.status_requester.request(
891
+ return await self.status_requester.request(
915
892
  response_type=inputs.ModStatusBinSensors,
916
893
  request_pck=PckGenerator.request_bin_sensors_status(),
917
894
  max_age=max_age,
918
895
  )
919
896
 
920
- return cast(inputs.ModStatusBinSensors, result)
921
-
922
897
  async def request_status_variable(
923
898
  self,
924
899
  variable: lcn_defs.Var,
@@ -929,17 +904,17 @@ class DeviceConnection:
929
904
  _LOGGER.info("Status requests are not supported for groups.")
930
905
  return None
931
906
 
932
- # do not use buffered response for old modules
933
- # (variable response is typeless)
934
- if self.serials.software_serial < 0x170206:
935
- if not lcn_defs.Var.has_type_in_response(
936
- variable, self.serials.software_serial
937
- ):
938
- try:
939
- await asyncio.wait_for(self.last_var_lock.acquire(), timeout=3.0)
940
- except asyncio.TimeoutError:
941
- pass
942
- self.last_requested_var_without_type_in_response = variable
907
+ response_variable = variable
908
+
909
+ # for old modules the variable response is typeless
910
+ # - do not use concurrent requests
911
+ # - do not use buffered response
912
+ if has_typeless_response := not lcn_defs.Var.has_type_in_response(
913
+ variable, self.serials.software_serial
914
+ ):
915
+ await self.request_lock.acquire()
916
+ max_age = 0
917
+ response_variable = lcn_defs.Var.UNKNOWN
943
918
 
944
919
  result = await self.status_requester.request(
945
920
  response_type=inputs.ModStatusVar,
@@ -947,10 +922,19 @@ class DeviceConnection:
947
922
  variable, self.serials.software_serial
948
923
  ),
949
924
  max_age=max_age,
950
- var=variable,
925
+ var=response_variable,
951
926
  )
952
927
 
953
- return cast(inputs.ModStatusVar, result)
928
+ # for old modules (typeless response) we need to set the original variable
929
+ # - call input_callbacks with the original variable type
930
+ if result is not None and has_typeless_response:
931
+ result.var = variable
932
+ for input_callback in self.input_callbacks:
933
+ input_callback(result)
934
+
935
+ if self.request_lock.locked():
936
+ self.request_lock.release()
937
+ return result
954
938
 
955
939
  async def request_status_led_and_logic_ops(
956
940
  self, max_age: int = 0
@@ -960,14 +944,12 @@ class DeviceConnection:
960
944
  _LOGGER.info("Status requests are not supported for groups.")
961
945
  return None
962
946
 
963
- result = await self.status_requester.request(
947
+ return await self.status_requester.request(
964
948
  response_type=inputs.ModStatusLedsAndLogicOps,
965
949
  request_pck=PckGenerator.request_leds_and_logic_ops(),
966
950
  max_age=max_age,
967
951
  )
968
952
 
969
- return cast(inputs.ModStatusLedsAndLogicOps, result)
970
-
971
953
  async def request_status_locked_keys(
972
954
  self, max_age: int = 0
973
955
  ) -> inputs.ModStatusKeyLocks | None:
@@ -976,14 +958,12 @@ class DeviceConnection:
976
958
  _LOGGER.info("Status requests are not supported for groups.")
977
959
  return None
978
960
 
979
- result = await self.status_requester.request(
961
+ return await self.status_requester.request(
980
962
  response_type=inputs.ModStatusKeyLocks,
981
963
  request_pck=PckGenerator.request_key_lock_status(),
982
964
  max_age=max_age,
983
965
  )
984
966
 
985
- return cast(inputs.ModStatusKeyLocks, result)
986
-
987
967
  # Request module properties
988
968
 
989
969
  async def request_serials(self, max_age: int = 0) -> Serials:
@@ -992,23 +972,20 @@ class DeviceConnection:
992
972
  _LOGGER.info("Status requests are not supported for groups.")
993
973
  return Serials(-1, -1, -1, lcn_defs.HardwareType.UNKNOWN)
994
974
 
995
- result = cast(
996
- inputs.ModSn | None,
997
- await self.status_requester.request(
998
- response_type=inputs.ModSn,
999
- request_pck=PckGenerator.request_serial(),
1000
- max_age=max_age,
1001
- ),
975
+ result = await self.status_requester.request(
976
+ response_type=inputs.ModSn,
977
+ request_pck=PckGenerator.request_serial(),
978
+ max_age=max_age,
1002
979
  )
1003
980
 
1004
- if result is None:
1005
- return Serials(-1, -1, -1, lcn_defs.HardwareType.UNKNOWN)
1006
- return Serials(
1007
- result.hardware_serial,
1008
- result.manu,
1009
- result.software_serial,
1010
- result.hardware_type,
1011
- )
981
+ if isinstance(result, inputs.ModSn):
982
+ return Serials(
983
+ result.hardware_serial,
984
+ result.manu,
985
+ result.software_serial,
986
+ result.hardware_type,
987
+ )
988
+ return Serials(-1, -1, -1, lcn_defs.HardwareType.UNKNOWN)
1012
989
 
1013
990
  async def request_name(self, max_age: int = 0) -> str | None:
1014
991
  """Request module name."""
@@ -1016,7 +993,7 @@ class DeviceConnection:
1016
993
  _LOGGER.info("Status requests are not supported for groups.")
1017
994
  return None
1018
995
 
1019
- coros = [
996
+ coros = (
1020
997
  self.status_requester.request(
1021
998
  response_type=inputs.ModNameComment,
1022
999
  request_pck=PckGenerator.request_name(block_id),
@@ -1024,8 +1001,8 @@ class DeviceConnection:
1024
1001
  command="N",
1025
1002
  block_id=block_id,
1026
1003
  )
1027
- for block_id in [0, 1]
1028
- ]
1004
+ for block_id in (0, 1)
1005
+ )
1029
1006
 
1030
1007
  coro_results = [await coro for coro in coros]
1031
1008
  if not all(coro_results):
@@ -1040,7 +1017,7 @@ class DeviceConnection:
1040
1017
  _LOGGER.info("Status requests are not supported for groups.")
1041
1018
  return None
1042
1019
 
1043
- coros = [
1020
+ coros = (
1044
1021
  self.status_requester.request(
1045
1022
  response_type=inputs.ModNameComment,
1046
1023
  request_pck=PckGenerator.request_comment(block_id),
@@ -1048,15 +1025,15 @@ class DeviceConnection:
1048
1025
  command="K",
1049
1026
  block_id=block_id,
1050
1027
  )
1051
- for block_id in [0, 1, 2]
1052
- ]
1028
+ for block_id in (0, 1, 2)
1029
+ )
1053
1030
 
1054
1031
  coro_results = [await coro for coro in coros]
1055
1032
  if not all(coro_results):
1056
1033
  return None
1057
1034
  results = cast(list[inputs.ModNameComment], coro_results)
1058
- name = "".join([result.text for result in results if result])
1059
- return name
1035
+ comment = "".join([result.text for result in results if result])
1036
+ return comment
1060
1037
 
1061
1038
  async def request_oem_text(self, max_age: int = 0) -> str | None:
1062
1039
  """Request module name."""
@@ -1064,7 +1041,7 @@ class DeviceConnection:
1064
1041
  _LOGGER.info("Status requests are not supported for groups.")
1065
1042
  return None
1066
1043
 
1067
- coros = [
1044
+ coros = (
1068
1045
  self.status_requester.request(
1069
1046
  response_type=inputs.ModNameComment,
1070
1047
  request_pck=PckGenerator.request_oem_text(block_id),
@@ -1072,19 +1049,19 @@ class DeviceConnection:
1072
1049
  command="O",
1073
1050
  block_id=block_id,
1074
1051
  )
1075
- for block_id in [0, 1, 2, 3]
1076
- ]
1052
+ for block_id in (0, 1, 2, 3)
1053
+ )
1077
1054
 
1078
1055
  coro_results = [await coro for coro in coros]
1079
1056
  if not all(coro_results):
1080
1057
  return None
1081
1058
  results = cast(list[inputs.ModNameComment], coro_results)
1082
- name = "".join([result.text for result in results if result])
1083
- return name
1059
+ oem_text = "".join([result.text for result in results if result])
1060
+ return oem_text
1084
1061
 
1085
1062
  async def request_group_memberships(
1086
1063
  self, dynamic: bool = False, max_age: int = 0
1087
- ) -> set[LcnAddr]:
1064
+ ) -> set[LcnAddr] | None:
1088
1065
  """Request module static/dynamic group memberships."""
1089
1066
  if self.addr.is_group:
1090
1067
  _LOGGER.info("Status requests are not supported for groups.")
@@ -1100,5 +1077,6 @@ class DeviceConnection:
1100
1077
  max_age=max_age,
1101
1078
  dynamic=dynamic,
1102
1079
  )
1103
-
1104
- return set(cast(inputs.ModStatusGroups, result).groups)
1080
+ if result is not None:
1081
+ return set(result.groups)
1082
+ return None
pypck/inputs.py CHANGED
@@ -26,6 +26,7 @@ class Input:
26
26
 
27
27
  def __init__(self) -> None:
28
28
  """Construct Input object."""
29
+ self.pck = ""
29
30
 
30
31
  @staticmethod
31
32
  def try_parse(data: str) -> list[Input] | None:
@@ -1368,9 +1369,11 @@ class InputParser:
1368
1369
  :rtype: List with instances of :class:`~pypck.input.Input`
1369
1370
  """
1370
1371
  for parser in InputParser.parsers:
1371
- ret: list[Input] | None = parser.try_parse(data)
1372
- if ret is not None:
1373
- return ret
1372
+ returns: list[Input] | None = parser.try_parse(data)
1373
+ if returns is not None:
1374
+ for ret in returns:
1375
+ ret.pck = data
1376
+ return returns
1374
1377
 
1375
1378
  # We must never get to this point since the Unknown parser matches
1376
1379
  # everything.
pypck/pck_commands.py CHANGED
@@ -880,20 +880,20 @@ class PckGenerator:
880
880
  if software_serial >= 0x170206:
881
881
  var_id = lcn_defs.Var.to_var_id(var)
882
882
  if var_id != -1:
883
- return f"MWT{var_id + 1:03d}"
883
+ return f"MWT{var_id + 1}"
884
884
 
885
885
  set_point_id = lcn_defs.Var.to_set_point_id(var)
886
886
  if set_point_id != -1:
887
- return f"MWS{set_point_id + 1:03d}"
887
+ return f"MWS{set_point_id + 1}"
888
888
 
889
889
  thrs_register_id = lcn_defs.Var.to_thrs_register_id(var)
890
890
  if thrs_register_id != -1:
891
891
  # Whole register
892
- return f"SE{thrs_register_id + 1:03d}"
892
+ return f"SE{thrs_register_id + 1}"
893
893
 
894
894
  s0_id = lcn_defs.Var.to_s0_id(var)
895
895
  if s0_id != -1:
896
- return f"MWC{s0_id + 1:03d}"
896
+ return f"MWC{s0_id + 1}"
897
897
  else:
898
898
  if var == lcn_defs.Var.VAR1ORTVAR:
899
899
  pck = "MWV"
pypck/status_requester.py CHANGED
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import logging
7
7
  from dataclasses import dataclass, field
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
9
9
 
10
10
  from pypck import inputs
11
11
 
@@ -14,147 +14,142 @@ if TYPE_CHECKING:
14
14
 
15
15
  _LOGGER = logging.getLogger(__name__)
16
16
 
17
+ ResponseT = TypeVar("ResponseT", bound=inputs.Input)
18
+
17
19
 
18
20
  @dataclass(unsafe_hash=True)
19
- class StatusRequest:
21
+ class StatusRequest(Generic[ResponseT]):
20
22
  """Data class for status requests."""
21
23
 
22
- type: type[inputs.Input] # Type of the input expected as response
24
+ type: type[ResponseT] # Type of the input expected as response
23
25
  parameters: frozenset[tuple[str, Any]] # {(parameter_name, parameter_value)}
24
26
  timestamp: float = field(
25
27
  compare=False
26
28
  ) # timestamp the response was received; -1=no timestamp
27
- response: asyncio.Future[inputs.Input] = field(
29
+ response: asyncio.Future[ResponseT] = field(
28
30
  compare=False
29
- ) # Future to hold the response input object
31
+ ) # the response input object
30
32
 
31
33
 
32
34
  class StatusRequester:
33
35
  """Handling of status requests."""
34
36
 
37
+ current_request: StatusRequest[inputs.Input] | None
38
+
35
39
  def __init__(
36
40
  self,
37
41
  device_connection: DeviceConnection,
38
42
  ) -> None:
39
43
  """Initialize the context."""
40
44
  self.device_connection = device_connection
41
- self.last_requests: set[StatusRequest] = set()
45
+ self.current_request = None
46
+ self.request_cache: set[StatusRequest[inputs.Input]] = set()
47
+ self.max_response_age = self.device_connection.conn.settings["MAX_RESPONSE_AGE"]
48
+ self.request_lock = asyncio.Lock()
49
+
42
50
  self.unregister_inputs = self.device_connection.register_for_inputs(
43
51
  self.input_callback
44
52
  )
45
- self.max_response_age = self.device_connection.conn.settings["MAX_RESPONSE_AGE"]
46
- # asyncio.get_running_loop().create_task(self.prune_loop())
47
-
48
- async def prune_loop(self) -> None:
49
- """Periodically prune old status requests."""
50
- while True:
51
- await asyncio.sleep(self.max_response_age)
52
- self.prune_status_requests()
53
-
54
- def prune_status_requests(self) -> None:
55
- """Prune old status requests."""
56
- entries_to_remove = {
57
- request
58
- for request in self.last_requests
59
- if asyncio.get_running_loop().time() - request.timestamp
60
- > self.max_response_age
61
- }
62
- for entry in entries_to_remove:
63
- entry.response.cancel()
64
- self.last_requests.difference_update(entries_to_remove)
65
53
 
66
54
  def get_status_requests(
67
55
  self,
68
- request_type: type[inputs.Input],
56
+ request_type: type[ResponseT],
69
57
  parameters: frozenset[tuple[str, Any]] | None = None,
70
58
  max_age: int = 0,
71
- ) -> list[StatusRequest]:
59
+ ) -> list[StatusRequest[ResponseT]]:
72
60
  """Get the status requests for the given type and parameters."""
73
61
  if parameters is None:
74
62
  parameters = frozenset()
75
- loop = asyncio.get_running_loop()
76
63
  results = [
77
64
  request
78
- for request in self.last_requests
65
+ for request in self.request_cache
79
66
  if request.type == request_type
80
67
  and parameters.issubset(request.parameters)
81
68
  and (
82
69
  (request.timestamp == -1)
83
70
  or (max_age == -1)
84
- or (loop.time() - request.timestamp < max_age)
71
+ or (asyncio.get_running_loop().time() - request.timestamp < max_age)
85
72
  )
86
73
  ]
87
74
  results.sort(key=lambda request: request.timestamp, reverse=True)
88
- return results
75
+ return cast(list[StatusRequest[ResponseT]], results)
89
76
 
90
77
  def input_callback(self, inp: inputs.Input) -> None:
91
78
  """Handle incoming inputs and set the result for the corresponding requests."""
92
- requests = [
93
- request
94
- for request in self.get_status_requests(type(inp))
79
+ # Update current request (if it exists)
80
+ if (
81
+ self.current_request is not None
82
+ and not self.current_request.response.done()
83
+ ):
84
+ if isinstance(inp, self.current_request.type) and all(
85
+ getattr(inp, parameter_name) == parameter_value
86
+ for parameter_name, parameter_value in self.current_request.parameters
87
+ ):
88
+ self.current_request.timestamp = asyncio.get_running_loop().time()
89
+ self.current_request.response.set_result(inp)
90
+
91
+ # Update cached requests
92
+ for request in self.get_status_requests(type(inp)):
95
93
  if all(
96
94
  getattr(inp, parameter_name) == parameter_value
97
95
  for parameter_name, parameter_value in request.parameters
98
- )
99
- ]
100
- for request in requests:
101
- if request.response.done() or request.response.cancelled():
102
- continue
103
- request.timestamp = asyncio.get_running_loop().time()
104
- request.response.set_result(inp)
96
+ ):
97
+ request.timestamp = asyncio.get_running_loop().time()
98
+ request.response = asyncio.get_running_loop().create_future()
99
+ request.response.set_result(inp)
105
100
 
106
101
  async def request(
107
102
  self,
108
- response_type: type[inputs.Input],
103
+ response_type: type[ResponseT],
109
104
  request_pck: str,
110
105
  request_acknowledge: bool = False,
111
106
  max_age: int = 0, # -1: no age limit / infinite age
112
107
  **request_kwargs: Any,
113
- ) -> inputs.Input | None:
108
+ ) -> ResponseT | None:
114
109
  """Execute a status request and wait for the response."""
115
- parameters = frozenset(request_kwargs.items())
116
-
117
- # check if we already have a received response for the current request
118
- if requests := self.get_status_requests(response_type, parameters, max_age):
119
- try:
120
- async with asyncio.timeout(
121
- self.device_connection.conn.settings["DEFAULT_TIMEOUT"]
122
- ):
123
- return await requests[0].response
124
- except asyncio.TimeoutError:
125
- return None
126
- except asyncio.CancelledError:
127
- return None
128
-
129
- # no stored request or forced request: set up a new request
130
- request = StatusRequest(
131
- response_type,
132
- frozenset(request_kwargs.items()),
133
- -1,
134
- asyncio.get_running_loop().create_future(),
135
- )
110
+ async with self.request_lock:
111
+ # check for matching request in cache
112
+ if requests := self.get_status_requests(
113
+ response_type,
114
+ frozenset(request_kwargs.items()),
115
+ max_age,
116
+ ):
117
+ _LOGGER.debug(
118
+ "from %s: %s (cached)",
119
+ self.device_connection.conn.connection_id,
120
+ requests[0].response.result().pck,
121
+ )
122
+ return requests[0].response.result()
123
+
124
+ # no matching request in cache
125
+ self.current_request = StatusRequest(
126
+ response_type,
127
+ frozenset(request_kwargs.items()),
128
+ -1,
129
+ asyncio.get_running_loop().create_future(),
130
+ )
136
131
 
137
- self.last_requests.discard(request)
138
- self.last_requests.add(request)
139
- result = None
140
- # send the request up to NUM_TRIES and wait for response future completion
141
- for _ in range(self.device_connection.conn.settings["NUM_TRIES"]):
142
- await self.device_connection.send_command(request_acknowledge, request_pck)
143
-
144
- try:
145
- async with asyncio.timeout(
146
- self.device_connection.conn.settings["DEFAULT_TIMEOUT"]
147
- ):
148
- # Need to shield the future. Otherwise it would get cancelled.
149
- result = await asyncio.shield(request.response)
132
+ result = None
133
+ # send the request up to NUM_TRIES and wait for response future completion
134
+ for _ in range(self.device_connection.conn.settings["NUM_TRIES"]):
135
+ await self.device_connection.send_command(
136
+ request_acknowledge, request_pck
137
+ )
138
+
139
+ try:
140
+ async with asyncio.timeout(
141
+ self.device_connection.conn.settings["DEFAULT_TIMEOUT"]
142
+ ):
143
+ # Need to shield the future. Otherwise it would get cancelled.
144
+ result = await asyncio.shield(self.current_request.response)
145
+ break
146
+ except asyncio.TimeoutError:
147
+ continue
148
+ except asyncio.CancelledError:
150
149
  break
151
- except asyncio.TimeoutError:
152
- continue
153
- except asyncio.CancelledError:
154
- break
155
-
156
- # if we got no results, remove the request from the set
157
- if result is None:
158
- request.response.cancel()
159
- self.last_requests.discard(request)
160
- return result
150
+
151
+ if result is not None: # add request to cache
152
+ self.request_cache.discard(self.current_request)
153
+ self.request_cache.add(self.current_request)
154
+
155
+ return cast(ResponseT | None, result)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypck
3
- Version: 0.9.7
3
+ Version: 0.9.9
4
4
  Summary: LCN-PCK library
5
5
  Home-page: https://github.com/alengwenus/pypck
6
6
  Author-email: Andre Lengwenus <alengwenus@gmail.com>
@@ -0,0 +1,15 @@
1
+ pypck/__init__.py,sha256=jVx-aBsV_LmBf6jiivMrMcBUofC_AOseywDafgOzAS4,323
2
+ pypck/connection.py,sha256=n3itRe8oQtw64vyWGYhl6j4QJC6wgeeHitBSn-Cl2_4,23330
3
+ pypck/device.py,sha256=1R9C4Wra8llzJph4eher-KPF2iF7uGOspq3eWcqTLyM,39591
4
+ pypck/helpers.py,sha256=_5doqIsSRpqdQNPIUsjFh813xKGuMuEFY6sNGobJGIk,1280
5
+ pypck/inputs.py,sha256=dw9ebhP9RBM9d-lPSFqRrFH1TOETNsT4RNschNjAnA8,46056
6
+ pypck/lcn_addr.py,sha256=N2Od8KuANOglqKjf596hJVH1SRcG7MhESKA5YYlDnbw,1946
7
+ pypck/lcn_defs.py,sha256=wSceYBwM46NqPwvff1hi8RluqUECmNY1gNcm1kDKTaI,43356
8
+ pypck/pck_commands.py,sha256=SL9zpsswRGCHjAWm4uKWFTqtSBx2jURFHzq86QrtwuU,50442
9
+ pypck/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pypck/status_requester.py,sha256=Ea9c9moA1Kxoh3U9tPVqHKAmnRwq-1vraP_cwqxGZt8,5774
11
+ pypck-0.9.9.dist-info/licenses/LICENSE,sha256=iYB6zyMJvShfAzQE7nhYFgLzzZuBmhasLw5fYP9KRz4,1023
12
+ pypck-0.9.9.dist-info/METADATA,sha256=HER_BuajbZll66fngbD2rQVTR6bcice7kOMW8bOLggk,2682
13
+ pypck-0.9.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ pypck-0.9.9.dist-info/top_level.txt,sha256=59ried49iFueDa5mQ_5BGVZcESjjzi4MZZKLcganvQA,6
15
+ pypck-0.9.9.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- pypck/__init__.py,sha256=jVx-aBsV_LmBf6jiivMrMcBUofC_AOseywDafgOzAS4,323
2
- pypck/connection.py,sha256=n3itRe8oQtw64vyWGYhl6j4QJC6wgeeHitBSn-Cl2_4,23330
3
- pypck/device.py,sha256=Ek-Zy4Id63vl43oW1pSafbDqRAfidhgoJI0F4EMWCXY,40375
4
- pypck/helpers.py,sha256=_5doqIsSRpqdQNPIUsjFh813xKGuMuEFY6sNGobJGIk,1280
5
- pypck/inputs.py,sha256=F7E8rprIhYzZnHARozt_hguYNgJaiNP3htrZ2E3Qa5I,45951
6
- pypck/lcn_addr.py,sha256=N2Od8KuANOglqKjf596hJVH1SRcG7MhESKA5YYlDnbw,1946
7
- pypck/lcn_defs.py,sha256=wSceYBwM46NqPwvff1hi8RluqUECmNY1gNcm1kDKTaI,43356
8
- pypck/pck_commands.py,sha256=eJxmh2e8EbKGpek97L2961Kr_nVfT8rKgJCN3YgjIQM,50458
9
- pypck/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- pypck/status_requester.py,sha256=10N5pbIBe_Ao-9ui_D7mCavk21BYZs9c-kxcTtmi-FI,5721
11
- pypck-0.9.7.dist-info/licenses/LICENSE,sha256=iYB6zyMJvShfAzQE7nhYFgLzzZuBmhasLw5fYP9KRz4,1023
12
- pypck-0.9.7.dist-info/METADATA,sha256=gooJ1CbK2mtAKuIEs8v3OKV_sDMHziMbmKHGPcEvsmE,2682
13
- pypck-0.9.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- pypck-0.9.7.dist-info/top_level.txt,sha256=59ried49iFueDa5mQ_5BGVZcESjjzi4MZZKLcganvQA,6
15
- pypck-0.9.7.dist-info/RECORD,,
File without changes