pyxcp 0.21.10__cp38-cp38-win_amd64.whl → 0.22.23__cp38-cp38-win_amd64.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.
Potentially problematic release.
This version of pyxcp might be problematic. Click here for more details.
- pyxcp/__init__.py +12 -20
- pyxcp/aml/EtasCANMonitoring.a2l +82 -83
- pyxcp/aml/XCP_Common.aml +0 -1
- pyxcp/aml/XCPonUSB.aml +1 -1
- pyxcp/aml/ifdata_CAN.a2l +0 -1
- pyxcp/aml/ifdata_Eth.a2l +0 -1
- pyxcp/aml/ifdata_Flx.a2l +0 -1
- pyxcp/aml/ifdata_SxI.a2l +0 -1
- pyxcp/aml/ifdata_USB.a2l +0 -1
- pyxcp/asam/types.py +4 -4
- pyxcp/asamkeydll.c +0 -1
- pyxcp/checksum.py +0 -1
- pyxcp/cmdline.py +32 -50
- pyxcp/config/__init__.py +1100 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +12 -13
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/bin.hpp +104 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +200 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +246 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +228 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +28 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +48 -0
- pyxcp/dllif.py +21 -18
- pyxcp/errormatrix.py +5 -3
- pyxcp/examples/conf_can.toml +4 -2
- pyxcp/examples/conf_can_vector.json +9 -9
- pyxcp/examples/conf_can_vector.toml +4 -2
- pyxcp/examples/conf_eth.toml +5 -2
- pyxcp/examples/conf_nixnet.json +18 -18
- pyxcp/examples/conf_sxi.json +7 -7
- pyxcp/examples/ex_arrow.py +109 -0
- pyxcp/examples/ex_csv.py +85 -0
- pyxcp/examples/ex_excel.py +95 -0
- pyxcp/examples/ex_mdf.py +124 -0
- pyxcp/examples/ex_sqlite.py +128 -0
- pyxcp/examples/run_daq.py +148 -0
- pyxcp/examples/xcp_policy.py +6 -7
- pyxcp/examples/xcp_read_benchmark.py +8 -6
- pyxcp/examples/xcp_skel.py +0 -2
- pyxcp/examples/xcp_unlock.py +1 -1
- pyxcp/examples/xcp_user_supplied_driver.py +1 -2
- pyxcp/examples/xcphello.py +6 -3
- pyxcp/examples/xcphello_recorder.py +4 -4
- pyxcp/master/__init__.py +1 -2
- pyxcp/master/errorhandler.py +107 -74
- pyxcp/master/master.py +201 -119
- pyxcp/py.typed +0 -0
- pyxcp/recorder/__init__.py +27 -6
- pyxcp/recorder/converter/__init__.py +37 -0
- pyxcp/recorder/lz4.c +129 -51
- pyxcp/recorder/lz4.h +45 -28
- pyxcp/recorder/lz4hc.c +560 -156
- pyxcp/recorder/lz4hc.h +1 -1
- pyxcp/recorder/mio.hpp +721 -767
- pyxcp/recorder/reader.hpp +139 -0
- pyxcp/recorder/reco.py +5 -8
- pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +18 -22
- pyxcp/recorder/rekorder.hpp +200 -587
- pyxcp/recorder/setup.py +11 -10
- pyxcp/recorder/test_reko.py +2 -3
- pyxcp/recorder/unfolder.hpp +1332 -0
- pyxcp/recorder/wrap.cpp +171 -9
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +15 -10
- pyxcp/scripts/xcp_id_scanner.py +2 -6
- pyxcp/scripts/xcp_info.py +101 -63
- pyxcp/scripts/xcp_profile.py +27 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +2 -2
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1132 -38
- pyxcp/tests/test_checksum.py +2 -1
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_frame_padding.py +6 -3
- pyxcp/tests/test_master.py +42 -31
- pyxcp/tests/test_transport.py +12 -12
- pyxcp/tests/test_utils.py +2 -5
- pyxcp/timing.py +0 -2
- pyxcp/transport/__init__.py +9 -9
- pyxcp/transport/base.py +149 -127
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +194 -167
- pyxcp/transport/eth.py +80 -82
- pyxcp/transport/sxi.py +106 -60
- pyxcp/transport/transport_wrapper.cpp +0 -0
- pyxcp/transport/usb_transport.py +65 -83
- pyxcp/types.py +69 -20
- pyxcp/utils.py +47 -16
- pyxcp/vector/map.py +1 -3
- {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/METADATA +27 -22
- pyxcp-0.22.23.dist-info/RECORD +128 -0
- {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
- {pyxcp-0.21.10.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
- pyxcp/config.py +0 -57
- pyxcp/cxx/asynchiofactory.hpp +0 -24
- pyxcp/cxx/blocking_client.cpp +0 -44
- pyxcp/cxx/blocking_socket.cpp +0 -43
- pyxcp/cxx/blocking_socket.hpp +0 -558
- pyxcp/cxx/concurrent_queue.hpp +0 -60
- pyxcp/cxx/eth.hpp +0 -57
- pyxcp/cxx/exceptions.hpp +0 -30
- pyxcp/cxx/iasyncioservice.hpp +0 -31
- pyxcp/cxx/iresource.hpp +0 -17
- pyxcp/cxx/isocket.hpp +0 -22
- pyxcp/cxx/linux/epoll.cpp +0 -51
- pyxcp/cxx/linux/epoll.hpp +0 -87
- pyxcp/cxx/linux/lit_tester.cpp +0 -19
- pyxcp/cxx/linux/socket.hpp +0 -234
- pyxcp/cxx/linux/timeout.hpp +0 -81
- pyxcp/cxx/memoryblock.hpp +0 -42
- pyxcp/cxx/pool.hpp +0 -81
- pyxcp/cxx/poolmgr.cpp +0 -6
- pyxcp/cxx/poolmgr.hpp +0 -31
- pyxcp/cxx/test_queue.cpp +0 -69
- pyxcp/cxx/timestamp.hpp +0 -84
- pyxcp/cxx/utils.cpp +0 -38
- pyxcp/cxx/utils.hpp +0 -29
- pyxcp/cxx/win/iocp.cpp +0 -242
- pyxcp/cxx/win/iocp.hpp +0 -42
- pyxcp/cxx/win/perhandledata.hpp +0 -24
- pyxcp/cxx/win/periodata.hpp +0 -97
- pyxcp/cxx/win/socket.hpp +0 -185
- pyxcp/cxx/win/timeout.hpp +0 -83
- pyxcp/examples/conf_can.json +0 -20
- pyxcp/examples/conf_eth.json +0 -8
- pyxcp/logger.py +0 -67
- pyxcp/tests/test_config.py +0 -62
- pyxcp/transport/candriver/__init__.py +0 -2
- pyxcp/transport/candriver/pc_canalystii.py +0 -27
- pyxcp/transport/candriver/pc_etas.py +0 -25
- pyxcp/transport/candriver/pc_gsusb.py +0 -23
- pyxcp/transport/candriver/pc_iscan.py +0 -23
- pyxcp/transport/candriver/pc_ixxat.py +0 -27
- pyxcp/transport/candriver/pc_kvaser.py +0 -39
- pyxcp/transport/candriver/pc_neovi.py +0 -31
- pyxcp/transport/candriver/pc_nican.py +0 -23
- pyxcp/transport/candriver/pc_nixnet.py +0 -23
- pyxcp/transport/candriver/pc_pcan.py +0 -25
- pyxcp/transport/candriver/pc_seeed.py +0 -28
- pyxcp/transport/candriver/pc_serial.py +0 -27
- pyxcp/transport/candriver/pc_slcan.py +0 -29
- pyxcp/transport/candriver/pc_socketcan.py +0 -23
- pyxcp/transport/candriver/pc_systec.py +0 -29
- pyxcp/transport/candriver/pc_usb2can.py +0 -30
- pyxcp/transport/candriver/pc_vector.py +0 -34
- pyxcp/transport/candriver/python_can.py +0 -101
- pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
- pyxcp/transport/cxx_ext/setup.py +0 -49
- pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
- pyxcp-0.21.10.dist-info/RECORD +0 -147
- rekorder.cp38-win_amd64.pyd +0 -0
- {pyxcp-0.21.10.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
pyxcp/master/errorhandler.py
CHANGED
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
2
|
"""Implements error-handling according to XCP spec.
|
|
4
3
|
"""
|
|
5
4
|
import functools
|
|
6
5
|
import logging
|
|
7
|
-
import os
|
|
8
6
|
import threading
|
|
9
7
|
import time
|
|
10
8
|
import types
|
|
11
9
|
from collections import namedtuple
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
from pyxcp.
|
|
17
|
-
from pyxcp.types import XcpResponseError
|
|
18
|
-
from pyxcp.types import XcpTimeoutError
|
|
10
|
+
from typing import Generic, List, Optional, TypeVar
|
|
11
|
+
|
|
12
|
+
import can
|
|
13
|
+
|
|
14
|
+
from pyxcp.errormatrix import ERROR_MATRIX, Action, PreAction
|
|
15
|
+
from pyxcp.types import COMMAND_CATEGORIES, XcpError, XcpResponseError, XcpTimeoutError
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
handle_errors = True # enable/disable XCP error-handling.
|
|
22
19
|
|
|
23
|
-
logger = logging.getLogger("pyxcp.errorhandler")
|
|
24
20
|
|
|
25
|
-
class SingletonBase
|
|
21
|
+
class SingletonBase:
|
|
26
22
|
_lock = threading.Lock()
|
|
27
23
|
|
|
28
24
|
def __new__(cls, *args, **kws):
|
|
@@ -31,7 +27,7 @@ class SingletonBase(object):
|
|
|
31
27
|
try:
|
|
32
28
|
cls._lock.acquire()
|
|
33
29
|
if not hasattr(cls, "_instance"):
|
|
34
|
-
cls._instance = super(
|
|
30
|
+
cls._instance = super().__new__(cls)
|
|
35
31
|
finally:
|
|
36
32
|
cls._lock.release()
|
|
37
33
|
return cls._instance
|
|
@@ -44,9 +40,19 @@ class InternalError(Exception):
|
|
|
44
40
|
"""Indicates an internal error, like invalid service."""
|
|
45
41
|
|
|
46
42
|
|
|
47
|
-
class
|
|
43
|
+
class SystemExit(Exception):
|
|
48
44
|
""""""
|
|
49
45
|
|
|
46
|
+
def __init__(self, msg: str, error_code: int = None, *args, **kws):
|
|
47
|
+
super().__init__(*args, **kws)
|
|
48
|
+
self.error_code = error_code
|
|
49
|
+
self.msg = msg
|
|
50
|
+
|
|
51
|
+
def __str__(self):
|
|
52
|
+
return f"SystemExit(error_code={self.error_code}, message={self.msg!r})"
|
|
53
|
+
|
|
54
|
+
__repr__ = __str__
|
|
55
|
+
|
|
50
56
|
|
|
51
57
|
class UnrecoverableError(Exception):
|
|
52
58
|
""""""
|
|
@@ -78,10 +84,10 @@ def getActions(service, error_code):
|
|
|
78
84
|
eh = getErrorHandler(service)
|
|
79
85
|
if eh is None:
|
|
80
86
|
raise InternalError(f"Invalid Service 0x{service:02x}")
|
|
81
|
-
print(f"Try to handle error -- Service: {service.name} Error-Code: {error_code}")
|
|
87
|
+
# print(f"Try to handle error -- Service: {service.name} Error-Code: {error_code}")
|
|
82
88
|
handler = eh.get(error_str)
|
|
83
89
|
if handler is None:
|
|
84
|
-
raise
|
|
90
|
+
raise SystemExit(f"Service {service.name!r} has no handler for {error_code}.", error_code=error_code)
|
|
85
91
|
preActions, actions = handler
|
|
86
92
|
return preActions, actions
|
|
87
93
|
|
|
@@ -89,8 +95,7 @@ def getActions(service, error_code):
|
|
|
89
95
|
def actionIter(actions):
|
|
90
96
|
"""Iterate over action from :file:`errormatrix.py`"""
|
|
91
97
|
if isinstance(actions, (tuple, list)):
|
|
92
|
-
|
|
93
|
-
yield item
|
|
98
|
+
yield from actions
|
|
94
99
|
else:
|
|
95
100
|
yield actions
|
|
96
101
|
|
|
@@ -116,12 +121,14 @@ class Arguments:
|
|
|
116
121
|
self.args = tuple(args)
|
|
117
122
|
self.kwargs = kwargs or {}
|
|
118
123
|
|
|
119
|
-
def __str__(self):
|
|
124
|
+
def __str__(self) -> str:
|
|
120
125
|
res = f"{self.__class__.__name__}(ARGS = {self.args}, KWS = {self.kwargs})"
|
|
121
126
|
return res
|
|
122
127
|
|
|
123
|
-
def __eq__(self, other):
|
|
124
|
-
return (self.args == other.args if other is not None else
|
|
128
|
+
def __eq__(self, other) -> bool:
|
|
129
|
+
return (self.args == other.args if other is not None else False) and (
|
|
130
|
+
self.kwargs == other.kwargs if other is not None else False
|
|
131
|
+
)
|
|
125
132
|
|
|
126
133
|
__repr__ = __str__
|
|
127
134
|
|
|
@@ -144,7 +151,7 @@ class Repeater:
|
|
|
144
151
|
|
|
145
152
|
def __init__(self, initial_value: int):
|
|
146
153
|
self._counter = initial_value
|
|
147
|
-
#print("\tREPEATER ctor", hex(id(self)))
|
|
154
|
+
# print("\tREPEATER ctor", hex(id(self)))
|
|
148
155
|
|
|
149
156
|
def repeat(self):
|
|
150
157
|
"""Check if repetition is required.
|
|
@@ -153,7 +160,7 @@ class Repeater:
|
|
|
153
160
|
-------
|
|
154
161
|
bool
|
|
155
162
|
"""
|
|
156
|
-
#print("\t\tCOUNTER:", hex(id(self)), self._counter)
|
|
163
|
+
# print("\t\tCOUNTER:", hex(id(self)), self._counter)
|
|
157
164
|
if self._counter == Repeater.INFINITE:
|
|
158
165
|
return True
|
|
159
166
|
elif self._counter > 0:
|
|
@@ -174,8 +181,6 @@ def display_error():
|
|
|
174
181
|
class Handler:
|
|
175
182
|
""""""
|
|
176
183
|
|
|
177
|
-
logger = logger
|
|
178
|
-
|
|
179
184
|
def __init__(self, instance, func, arguments, error_code=None):
|
|
180
185
|
self.instance = instance
|
|
181
186
|
if hasattr(func, "__closure__") and func.__closure__:
|
|
@@ -185,29 +190,40 @@ class Handler:
|
|
|
185
190
|
self.func = func
|
|
186
191
|
self.arguments = arguments
|
|
187
192
|
self.service = self.instance.service
|
|
188
|
-
self.
|
|
193
|
+
self._error_code: int = 0
|
|
194
|
+
if error_code is not None:
|
|
195
|
+
self._error_code = error_code
|
|
189
196
|
self._repeater = None
|
|
197
|
+
self.logger = logging.getLogger("PyXCP")
|
|
190
198
|
|
|
191
199
|
def __str__(self):
|
|
192
|
-
return f"Handler(func = {func_name(self.func)}
|
|
200
|
+
return f"Handler(func = {func_name(self.func)} -- {self.arguments} service = {self.service} error_code = {self.error_code})"
|
|
193
201
|
|
|
194
202
|
def __eq__(self, other):
|
|
195
203
|
if other is None:
|
|
196
204
|
return False
|
|
197
205
|
return (self.instance == other.instance) and (self.func == other.func) and (self.arguments == other.arguments)
|
|
198
206
|
|
|
207
|
+
@property
|
|
208
|
+
def error_code(self) -> int:
|
|
209
|
+
return self._error_code
|
|
210
|
+
|
|
211
|
+
@error_code.setter
|
|
212
|
+
def error_code(self, value: int) -> None:
|
|
213
|
+
self._error_code = value
|
|
214
|
+
|
|
199
215
|
@property
|
|
200
216
|
def repeater(self):
|
|
201
|
-
#print("\tGet repeater", hex(id(self._repeater)), self._repeater is None)
|
|
217
|
+
# print("\tGet repeater", hex(id(self._repeater)), self._repeater is None)
|
|
202
218
|
return self._repeater
|
|
203
219
|
|
|
204
220
|
@repeater.setter
|
|
205
221
|
def repeater(self, value):
|
|
206
|
-
#print("\tSet repeater", hex(id(value)))
|
|
222
|
+
# print("\tSet repeater", hex(id(value)))
|
|
207
223
|
self._repeater = value
|
|
208
224
|
|
|
209
225
|
def execute(self):
|
|
210
|
-
self.logger.debug(f"
|
|
226
|
+
self.logger.debug(f"Execute({func_name(self.func)} -- {self.arguments})")
|
|
211
227
|
if isinstance(self.func, types.MethodType):
|
|
212
228
|
return self.func(*self.arguments.args, **self.arguments.kwargs)
|
|
213
229
|
else:
|
|
@@ -227,40 +243,42 @@ class Handler:
|
|
|
227
243
|
fn = Function(self.instance.synch, Arguments())
|
|
228
244
|
result_pre_actions.append(fn)
|
|
229
245
|
elif item == PreAction.GET_SEED_UNLOCK:
|
|
230
|
-
raise NotImplementedError("GET_SEED_UNLOCK")
|
|
246
|
+
raise NotImplementedError("Pre-action GET_SEED_UNLOCK")
|
|
231
247
|
elif item == PreAction.SET_MTA:
|
|
232
248
|
fn = Function(self.instance.setMta, Arguments(self.instance.mta))
|
|
233
249
|
result_pre_actions.append(fn)
|
|
234
250
|
elif item == PreAction.SET_DAQ_PTR:
|
|
235
251
|
fn = Function(self.instance.setDaqPtr, Arguments(self.instance.currentDaqPtr))
|
|
236
252
|
elif item == PreAction.START_STOP_X:
|
|
237
|
-
raise NotImplementedError("START_STOP_X")
|
|
253
|
+
raise NotImplementedError("Pre-action START_STOP_X")
|
|
238
254
|
elif item == PreAction.REINIT_DAQ:
|
|
239
|
-
raise NotImplementedError("REINIT_DAQ")
|
|
255
|
+
raise NotImplementedError("Pre-action REINIT_DAQ")
|
|
240
256
|
elif item == PreAction.DISPLAY_ERROR:
|
|
241
257
|
pass
|
|
242
258
|
elif item == PreAction.DOWNLOAD:
|
|
243
|
-
raise NotImplementedError("DOWNLOAD")
|
|
259
|
+
raise NotImplementedError("Pre-action DOWNLOAD")
|
|
244
260
|
elif item == PreAction.PROGRAM:
|
|
245
|
-
raise NotImplementedError("PROGRAM")
|
|
261
|
+
raise NotImplementedError("Pre-action PROGRAM")
|
|
246
262
|
elif item == PreAction.UPLOAD:
|
|
247
|
-
raise NotImplementedError("UPLOAD")
|
|
263
|
+
raise NotImplementedError("Pre-action UPLOAD")
|
|
248
264
|
elif item == PreAction.UNLOCK_SLAVE:
|
|
249
265
|
resource = COMMAND_CATEGORIES.get(self.instance.service) # noqa: F841
|
|
250
|
-
raise NotImplementedError("UNLOCK_SLAVE")
|
|
266
|
+
raise NotImplementedError("Pre-action UNLOCK_SLAVE")
|
|
251
267
|
for item in actionIter(actions):
|
|
252
268
|
if item == Action.NONE:
|
|
253
269
|
pass
|
|
254
270
|
elif item == Action.DISPLAY_ERROR:
|
|
255
|
-
raise
|
|
271
|
+
raise SystemExit("Could not proceed due to unhandled error (DISPLAY_ERROR).", self.error_code)
|
|
256
272
|
elif item == Action.RETRY_SYNTAX:
|
|
257
|
-
raise
|
|
273
|
+
raise SystemExit("Could not proceed due to unhandled error (RETRY_SYNTAX).", self.error_code)
|
|
258
274
|
elif item == Action.RETRY_PARAM:
|
|
259
|
-
raise
|
|
275
|
+
raise SystemExit("Could not proceed due to unhandled error (RETRY_PARAM).", self.error_code)
|
|
260
276
|
elif item == Action.USE_A2L:
|
|
261
|
-
raise
|
|
277
|
+
raise SystemExit("Could not proceed due to unhandled error (USE_A2L).", self.error_code)
|
|
262
278
|
elif item == Action.USE_ALTERATIVE:
|
|
263
|
-
raise
|
|
279
|
+
raise SystemExit(
|
|
280
|
+
"Could not proceed due to unhandled error (USE_ALTERATIVE).", self.error_code
|
|
281
|
+
) # TODO: check alternatives.
|
|
264
282
|
elif item == Action.REPEAT:
|
|
265
283
|
repetitionCount = Repeater.REPEAT
|
|
266
284
|
elif item == Action.REPEAT_2_TIMES:
|
|
@@ -268,49 +286,53 @@ class Handler:
|
|
|
268
286
|
elif item == Action.REPEAT_INF_TIMES:
|
|
269
287
|
repetitionCount = Repeater.INFINITE
|
|
270
288
|
elif item == Action.RESTART_SESSION:
|
|
271
|
-
raise
|
|
289
|
+
raise SystemExit("Could not proceed due to unhandled error (RESTART_SESSION).", self.error_code)
|
|
272
290
|
elif item == Action.TERMINATE_SESSION:
|
|
273
|
-
raise
|
|
291
|
+
raise SystemExit("Could not proceed due to unhandled error (TERMINATE_SESSION).", self.error_code)
|
|
274
292
|
elif item == Action.SKIP:
|
|
275
293
|
pass
|
|
276
294
|
elif item == Action.NEW_FLASH_WARE:
|
|
277
|
-
raise
|
|
295
|
+
raise SystemExit("Could not proceed due to unhandled error (NEW_FLASH_WARE)", self.error_code)
|
|
278
296
|
return result_pre_actions, result_actions, Repeater(repetitionCount)
|
|
279
297
|
|
|
280
298
|
|
|
281
|
-
|
|
299
|
+
T = TypeVar("T")
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class HandlerStack(Generic[T]):
|
|
282
303
|
""""""
|
|
283
304
|
|
|
284
|
-
def __init__(self):
|
|
285
|
-
self._stack = []
|
|
305
|
+
def __init__(self) -> None:
|
|
306
|
+
self._stack: List[T] = []
|
|
286
307
|
|
|
287
|
-
def push(self,
|
|
288
|
-
if
|
|
289
|
-
self._stack.append(
|
|
308
|
+
def push(self, value: T):
|
|
309
|
+
if value != self.tos():
|
|
310
|
+
self._stack.append(value)
|
|
290
311
|
|
|
291
|
-
def pop(self):
|
|
312
|
+
def pop(self) -> None:
|
|
292
313
|
if len(self) > 0:
|
|
293
314
|
self._stack.pop()
|
|
294
315
|
|
|
295
|
-
def tos(self):
|
|
316
|
+
def tos(self) -> Optional[T]:
|
|
296
317
|
if len(self) > 0:
|
|
297
318
|
return self._stack[-1]
|
|
298
319
|
else:
|
|
299
320
|
return None
|
|
321
|
+
# raise ValueError("empty stack.")
|
|
300
322
|
|
|
301
|
-
def empty(self):
|
|
323
|
+
def empty(self) -> bool:
|
|
302
324
|
return self._stack == []
|
|
303
325
|
|
|
304
|
-
def __len__(self):
|
|
326
|
+
def __len__(self) -> int:
|
|
305
327
|
return len(self._stack)
|
|
306
328
|
|
|
307
|
-
def __repr__(self):
|
|
329
|
+
def __repr__(self) -> str:
|
|
308
330
|
result = []
|
|
309
331
|
for idx in range(len(self)):
|
|
310
332
|
result.append(str(self[idx]))
|
|
311
333
|
return "\n".join(result)
|
|
312
334
|
|
|
313
|
-
def __getitem__(self, ndx):
|
|
335
|
+
def __getitem__(self, ndx: int) -> T:
|
|
314
336
|
return self._stack[ndx]
|
|
315
337
|
|
|
316
338
|
__str__ = __repr__
|
|
@@ -319,44 +341,53 @@ class HandlerStack:
|
|
|
319
341
|
class Executor(SingletonBase):
|
|
320
342
|
""""""
|
|
321
343
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
344
|
+
def __init__(self):
|
|
345
|
+
self.handlerStack = HandlerStack()
|
|
346
|
+
self.repeater = None
|
|
347
|
+
self.logger = logging.getLogger("PyXCP")
|
|
348
|
+
self.previous_error_code = None
|
|
349
|
+
self.error_code = None
|
|
350
|
+
self.func = None
|
|
351
|
+
self.arguments = None
|
|
329
352
|
|
|
330
353
|
def __call__(self, inst, func, arguments):
|
|
331
|
-
self.logger.debug(f"__call__({func.__qualname__})")
|
|
332
354
|
self.inst = inst
|
|
333
355
|
self.func = func
|
|
334
356
|
self.arguments = arguments
|
|
335
357
|
handler = Handler(inst, func, arguments)
|
|
336
358
|
self.handlerStack.push(handler)
|
|
337
|
-
#print("\tENTER handler:", hex(id(handler)))
|
|
338
359
|
try:
|
|
339
360
|
while True:
|
|
340
361
|
try:
|
|
341
362
|
handler = self.handlerStack.tos()
|
|
342
|
-
#print("\t\tEXEC", hex(id(handler)))
|
|
343
363
|
res = handler.execute()
|
|
344
364
|
except XcpResponseError as e:
|
|
345
|
-
self.logger.
|
|
365
|
+
# self.logger.critical(f"XcpResponseError [{e.get_error_code()}]")
|
|
346
366
|
self.error_code = e.get_error_code()
|
|
347
|
-
|
|
348
|
-
|
|
367
|
+
handler.error_code = self.error_code
|
|
368
|
+
except XcpTimeoutError:
|
|
369
|
+
# self.logger.error(f"XcpTimeoutError [{str(e)}]")
|
|
349
370
|
self.error_code = XcpError.ERR_TIMEOUT
|
|
350
|
-
|
|
351
|
-
|
|
371
|
+
handler.error_code = self.error_code
|
|
372
|
+
except TimeoutError:
|
|
373
|
+
raise
|
|
374
|
+
except can.CanError:
|
|
375
|
+
# self.logger.critical(f"Exception raised by Python CAN [{str(e)}]")
|
|
376
|
+
raise
|
|
377
|
+
except Exception:
|
|
378
|
+
# self.logger.critical(f"Exception [{str(e)}]")
|
|
379
|
+
raise
|
|
352
380
|
else:
|
|
353
381
|
self.error_code = None
|
|
354
|
-
# print("\t\t\t*** SUCCESS ***")
|
|
355
382
|
self.handlerStack.pop()
|
|
356
383
|
if self.handlerStack.empty():
|
|
357
|
-
# print("OK, all handlers passed: '{}'.".format(res))
|
|
358
384
|
return res
|
|
359
385
|
|
|
386
|
+
if self.error_code == XcpError.ERR_CMD_SYNCH:
|
|
387
|
+
# Don't care about SYNCH for now...
|
|
388
|
+
self.inst.logger.info("SYNCH received.")
|
|
389
|
+
continue
|
|
390
|
+
|
|
360
391
|
if self.error_code is not None:
|
|
361
392
|
preActions, actions, repeater = handler.actions(*getActions(inst.service, self.error_code))
|
|
362
393
|
if handler.repeater is None:
|
|
@@ -368,7 +399,9 @@ class Executor(SingletonBase):
|
|
|
368
399
|
if handler.repeater.repeat():
|
|
369
400
|
continue
|
|
370
401
|
else:
|
|
371
|
-
raise UnrecoverableError(
|
|
402
|
+
raise UnrecoverableError(
|
|
403
|
+
f"Max. repetition count reached while trying to execute service {handler.func.__name__!r}."
|
|
404
|
+
)
|
|
372
405
|
finally:
|
|
373
406
|
# cleanup of class variables
|
|
374
407
|
self.previous_error_code = None
|