pyxcp 0.25.4__cp313-cp313-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.
Files changed (157) hide show
  1. pyxcp/__init__.py +20 -0
  2. pyxcp/aml/EtasCANMonitoring.a2l +82 -0
  3. pyxcp/aml/EtasCANMonitoring.aml +67 -0
  4. pyxcp/aml/XCP_Common.aml +408 -0
  5. pyxcp/aml/XCPonCAN.aml +78 -0
  6. pyxcp/aml/XCPonEth.aml +33 -0
  7. pyxcp/aml/XCPonFlx.aml +113 -0
  8. pyxcp/aml/XCPonSxI.aml +66 -0
  9. pyxcp/aml/XCPonUSB.aml +106 -0
  10. pyxcp/aml/ifdata_CAN.a2l +20 -0
  11. pyxcp/aml/ifdata_Eth.a2l +11 -0
  12. pyxcp/aml/ifdata_Flx.a2l +94 -0
  13. pyxcp/aml/ifdata_SxI.a2l +13 -0
  14. pyxcp/aml/ifdata_USB.a2l +81 -0
  15. pyxcp/asam/__init__.py +0 -0
  16. pyxcp/asam/types.py +131 -0
  17. pyxcp/asamkeydll.c +116 -0
  18. pyxcp/asamkeydll.exe +0 -0
  19. pyxcp/asamkeydll.sh +2 -0
  20. pyxcp/checksum.py +732 -0
  21. pyxcp/cmdline.py +71 -0
  22. pyxcp/config/__init__.py +1257 -0
  23. pyxcp/config/legacy.py +120 -0
  24. pyxcp/constants.py +47 -0
  25. pyxcp/cpp_ext/__init__.py +0 -0
  26. pyxcp/cpp_ext/aligned_buffer.hpp +168 -0
  27. pyxcp/cpp_ext/bin.hpp +105 -0
  28. pyxcp/cpp_ext/blockmem.hpp +58 -0
  29. pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
  30. pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
  31. pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
  32. pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd +0 -0
  33. pyxcp/cpp_ext/daqlist.hpp +374 -0
  34. pyxcp/cpp_ext/event.hpp +67 -0
  35. pyxcp/cpp_ext/extension_wrapper.cpp +131 -0
  36. pyxcp/cpp_ext/framing.hpp +360 -0
  37. pyxcp/cpp_ext/helper.hpp +280 -0
  38. pyxcp/cpp_ext/mcobject.hpp +248 -0
  39. pyxcp/cpp_ext/sxi_framing.hpp +332 -0
  40. pyxcp/cpp_ext/tsqueue.hpp +46 -0
  41. pyxcp/daq_stim/__init__.py +291 -0
  42. pyxcp/daq_stim/optimize/__init__.py +67 -0
  43. pyxcp/daq_stim/optimize/binpacking.py +41 -0
  44. pyxcp/daq_stim/scheduler.cpp +62 -0
  45. pyxcp/daq_stim/scheduler.hpp +75 -0
  46. pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
  47. pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
  48. pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
  49. pyxcp/daq_stim/stim.cp313-win_amd64.pyd +0 -0
  50. pyxcp/daq_stim/stim.cpp +13 -0
  51. pyxcp/daq_stim/stim.hpp +604 -0
  52. pyxcp/daq_stim/stim_wrapper.cpp +50 -0
  53. pyxcp/dllif.py +100 -0
  54. pyxcp/errormatrix.py +878 -0
  55. pyxcp/examples/conf_can.toml +19 -0
  56. pyxcp/examples/conf_can_user.toml +16 -0
  57. pyxcp/examples/conf_can_vector.json +11 -0
  58. pyxcp/examples/conf_can_vector.toml +11 -0
  59. pyxcp/examples/conf_eth.toml +9 -0
  60. pyxcp/examples/conf_nixnet.json +20 -0
  61. pyxcp/examples/conf_socket_can.toml +12 -0
  62. pyxcp/examples/run_daq.py +165 -0
  63. pyxcp/examples/xcp_policy.py +60 -0
  64. pyxcp/examples/xcp_read_benchmark.py +38 -0
  65. pyxcp/examples/xcp_skel.py +48 -0
  66. pyxcp/examples/xcp_unlock.py +36 -0
  67. pyxcp/examples/xcp_user_supplied_driver.py +43 -0
  68. pyxcp/examples/xcphello.py +65 -0
  69. pyxcp/examples/xcphello_recorder.py +107 -0
  70. pyxcp/master/__init__.py +10 -0
  71. pyxcp/master/errorhandler.py +677 -0
  72. pyxcp/master/master.py +2641 -0
  73. pyxcp/py.typed +0 -0
  74. pyxcp/recorder/.idea/.gitignore +8 -0
  75. pyxcp/recorder/.idea/misc.xml +4 -0
  76. pyxcp/recorder/.idea/modules.xml +8 -0
  77. pyxcp/recorder/.idea/recorder.iml +6 -0
  78. pyxcp/recorder/.idea/sonarlint/issuestore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +7 -0
  79. pyxcp/recorder/.idea/sonarlint/issuestore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  80. pyxcp/recorder/.idea/sonarlint/issuestore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  81. pyxcp/recorder/.idea/sonarlint/issuestore/index.pb +7 -0
  82. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +0 -0
  83. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  84. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  85. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/index.pb +7 -0
  86. pyxcp/recorder/.idea/vcs.xml +10 -0
  87. pyxcp/recorder/__init__.py +96 -0
  88. pyxcp/recorder/build_clang.cmd +1 -0
  89. pyxcp/recorder/build_clang.sh +2 -0
  90. pyxcp/recorder/build_gcc.cmd +1 -0
  91. pyxcp/recorder/build_gcc.sh +2 -0
  92. pyxcp/recorder/build_gcc_arm.sh +2 -0
  93. pyxcp/recorder/converter/__init__.py +444 -0
  94. pyxcp/recorder/lz4.c +2829 -0
  95. pyxcp/recorder/lz4.h +879 -0
  96. pyxcp/recorder/lz4hc.c +2041 -0
  97. pyxcp/recorder/lz4hc.h +413 -0
  98. pyxcp/recorder/mio.hpp +1714 -0
  99. pyxcp/recorder/reader.hpp +138 -0
  100. pyxcp/recorder/reco.py +278 -0
  101. pyxcp/recorder/recorder.rst +0 -0
  102. pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
  103. pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
  104. pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
  105. pyxcp/recorder/rekorder.cp313-win_amd64.pyd +0 -0
  106. pyxcp/recorder/rekorder.cpp +59 -0
  107. pyxcp/recorder/rekorder.hpp +274 -0
  108. pyxcp/recorder/setup.py +41 -0
  109. pyxcp/recorder/test_reko.py +34 -0
  110. pyxcp/recorder/unfolder.hpp +1354 -0
  111. pyxcp/recorder/wrap.cpp +184 -0
  112. pyxcp/recorder/writer.hpp +302 -0
  113. pyxcp/scripts/__init__.py +0 -0
  114. pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
  115. pyxcp/scripts/xcp_examples.py +64 -0
  116. pyxcp/scripts/xcp_fetch_a2l.py +40 -0
  117. pyxcp/scripts/xcp_id_scanner.py +18 -0
  118. pyxcp/scripts/xcp_info.py +159 -0
  119. pyxcp/scripts/xcp_profile.py +26 -0
  120. pyxcp/scripts/xmraw_converter.py +31 -0
  121. pyxcp/stim/__init__.py +0 -0
  122. pyxcp/tests/test_asam_types.py +24 -0
  123. pyxcp/tests/test_binpacking.py +186 -0
  124. pyxcp/tests/test_can.py +1324 -0
  125. pyxcp/tests/test_checksum.py +95 -0
  126. pyxcp/tests/test_daq.py +193 -0
  127. pyxcp/tests/test_daq_opt.py +426 -0
  128. pyxcp/tests/test_frame_padding.py +156 -0
  129. pyxcp/tests/test_framing.py +262 -0
  130. pyxcp/tests/test_master.py +2116 -0
  131. pyxcp/tests/test_transport.py +177 -0
  132. pyxcp/tests/test_utils.py +30 -0
  133. pyxcp/timing.py +60 -0
  134. pyxcp/transport/__init__.py +13 -0
  135. pyxcp/transport/base.py +484 -0
  136. pyxcp/transport/base_transport.hpp +0 -0
  137. pyxcp/transport/can.py +660 -0
  138. pyxcp/transport/eth.py +254 -0
  139. pyxcp/transport/hdf5_policy.py +129 -0
  140. pyxcp/transport/sxi.py +209 -0
  141. pyxcp/transport/transport_ext.cp310-win_amd64.pyd +0 -0
  142. pyxcp/transport/transport_ext.cp311-win_amd64.pyd +0 -0
  143. pyxcp/transport/transport_ext.cp312-win_amd64.pyd +0 -0
  144. pyxcp/transport/transport_ext.cp313-win_amd64.pyd +0 -0
  145. pyxcp/transport/transport_ext.hpp +214 -0
  146. pyxcp/transport/transport_wrapper.cpp +249 -0
  147. pyxcp/transport/usb_transport.py +229 -0
  148. pyxcp/types.py +987 -0
  149. pyxcp/utils/__init__.py +127 -0
  150. pyxcp/utils/cli.py +78 -0
  151. pyxcp/vector/__init__.py +0 -0
  152. pyxcp/vector/map.py +82 -0
  153. pyxcp-0.25.4.dist-info/METADATA +341 -0
  154. pyxcp-0.25.4.dist-info/RECORD +157 -0
  155. pyxcp-0.25.4.dist-info/WHEEL +4 -0
  156. pyxcp-0.25.4.dist-info/entry_points.txt +9 -0
  157. pyxcp-0.25.4.dist-info/licenses/LICENSE +165 -0
@@ -0,0 +1,177 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+ import serial
5
+ from can.bus import BusABC
6
+
7
+ import pyxcp.transport.base as tr
8
+
9
+
10
+ def create_mock_serial():
11
+ """Create a mock serial port for testing."""
12
+ mock_serial = mock.MagicMock(spec=serial.Serial)
13
+ mock_serial.portstr = "MOCK_PORT"
14
+ mock_serial.in_waiting = 0
15
+ mock_serial.read.return_value = b""
16
+ mock_serial.is_open = True
17
+ return mock_serial
18
+
19
+
20
+ def create_mock_can_interface():
21
+ """Create a mock CAN interface for testing."""
22
+ mock_can = mock.MagicMock(spec=BusABC)
23
+ mock_can.filters = []
24
+ mock_can.state = "ACTIVE"
25
+ mock_can.recv.return_value = None
26
+ return mock_can
27
+
28
+
29
+ # Mock CAN interface configuration class
30
+ class MockCanInterfaceConfig:
31
+ OPTIONAL_BASE_PARAMS = []
32
+ CAN_PARAM_MAP = {}
33
+
34
+ @classmethod
35
+ def class_own_traits(cls):
36
+ return {}
37
+
38
+
39
+ def create_config():
40
+ # Create a class to simulate the config structure
41
+ class EthConfig:
42
+ def __init__(self):
43
+ self.host = "localhost"
44
+ self.port = 5555
45
+ self.bind_to_address = ""
46
+ self.bind_to_port = 0
47
+ self.protocol = "UDP"
48
+ self.ipv6 = False
49
+ self.tcp_nodelay = False
50
+
51
+ class SxiConfig:
52
+ def __init__(self):
53
+ self.port = "MOCK_PORT" # This won't be used with the mock
54
+ self.bitrate = 115200
55
+ self.bytesize = 8
56
+ self.parity = "N"
57
+ self.stopbits = 1
58
+ self.mode = "NORMAL"
59
+ self.header_format = "HEADER_LEN_BYTE"
60
+ self.tail_format = ""
61
+ self.framing = 0
62
+ self.esc_sync = 0
63
+ self.esc_esc = 0
64
+
65
+ class CanConfig:
66
+ def __init__(self):
67
+ self.can_id_master = 1
68
+ self.can_id_slave = 2
69
+ self.interface = "MockCanInterface"
70
+ self.channel = "vcan0"
71
+ self.use_default_listener = False # Don't start the listener
72
+ self.fd = False
73
+ self.max_dlc_required = False
74
+ self.padding_value = 0
75
+ self.timeout = 1.0
76
+ self.daq_identifier = [] # Empty list for DAQ identifiers
77
+
78
+ # Add the MockCanInterface attribute
79
+ self.MockCanInterface = MockCanInterfaceConfig()
80
+
81
+ # Special flag for testing
82
+ self.testing = True
83
+
84
+ class Config:
85
+ def __init__(self):
86
+ # Set attributes directly on the class for BaseTransport.load_config
87
+ self.eth = EthConfig()
88
+ self.sxi = SxiConfig()
89
+ self.can = CanConfig()
90
+
91
+ # Set attributes for BaseTransport.__init__
92
+ self.create_daq_timestamps = False
93
+ self.alignment = 1
94
+ self.timeout = 1.0
95
+
96
+ return Config()
97
+
98
+
99
+ @mock.patch("pyxcp.transport.can.detect_available_configs")
100
+ @mock.patch("pyxcp.transport.can.CAN_INTERFACE_MAP")
101
+ def test_factory_works(mock_can_interface_map, mock_detect_configs):
102
+ # Mock the detect_available_configs function to return an empty list
103
+ mock_detect_configs.return_value = []
104
+
105
+ # Mock the CAN_INTERFACE_MAP to return an instance of our MockCanInterfaceConfig for any key
106
+ mock_can_interface_map.__getitem__.return_value = MockCanInterfaceConfig()
107
+
108
+ config = create_config()
109
+ mock_serial_port = create_mock_serial()
110
+ mock_can_interface = create_mock_can_interface()
111
+
112
+ # Test ETH transport
113
+ assert isinstance(tr.create_transport("eth", config=config), tr.BaseTransport)
114
+
115
+ # Test SXI transport with mock serial port
116
+ assert isinstance(tr.create_transport("sxi", config=config, transport_layer_interface=mock_serial_port), tr.BaseTransport)
117
+
118
+ # Test CAN transport with mock CAN interface
119
+ # assert isinstance(
120
+ # tr.create_transport("can", config=config, transport_layer_interface=mock_can_interface),
121
+ # tr.BaseTransport,
122
+ # )
123
+
124
+
125
+ @mock.patch("pyxcp.transport.can.detect_available_configs")
126
+ @mock.patch("pyxcp.transport.can.CAN_INTERFACE_MAP")
127
+ def test_factory_works_case_insensitive(mock_can_interface_map, mock_detect_configs):
128
+ # Mock the detect_available_configs function to return an empty list
129
+ mock_detect_configs.return_value = []
130
+
131
+ # Mock the CAN_INTERFACE_MAP to return an instance of our MockCanInterfaceConfig for any key
132
+ mock_can_interface_map.__getitem__.return_value = MockCanInterfaceConfig()
133
+
134
+ config = create_config()
135
+ mock_serial_port = create_mock_serial()
136
+ mock_can_interface = create_mock_can_interface()
137
+
138
+ # Test ETH transport with uppercase name
139
+ assert isinstance(tr.create_transport("ETH", config=config), tr.BaseTransport)
140
+
141
+ # Test SXI transport with uppercase name and mock serial port
142
+ assert isinstance(tr.create_transport("SXI", config=config, transport_layer_interface=mock_serial_port), tr.BaseTransport)
143
+
144
+ # Test CAN transport with uppercase name and mock CAN interface
145
+ # assert isinstance(
146
+ # tr.create_transport("CAN", config=config, transport_layer_interface=mock_can_interface),
147
+ # tr.BaseTransport,
148
+ # )
149
+
150
+
151
+ def test_factory_invalid_transport_name_raises():
152
+ with pytest.raises(ValueError):
153
+ tr.create_transport("xCp")
154
+
155
+
156
+ def test_transport_names():
157
+ transports = tr.available_transports()
158
+
159
+ assert "can" in transports
160
+ assert "eth" in transports
161
+ assert "sxi" in transports
162
+
163
+
164
+ def test_transport_names_are_lower_case_only():
165
+ transports = tr.available_transports()
166
+
167
+ assert "CAN" not in transports
168
+ assert "ETH" not in transports
169
+ assert "SXI" not in transports
170
+
171
+
172
+ def test_transport_classes():
173
+ transports = tr.available_transports()
174
+
175
+ assert issubclass(transports.get("can"), tr.BaseTransport)
176
+ assert issubclass(transports.get("eth"), tr.BaseTransport)
177
+ assert issubclass(transports.get("sxi"), tr.BaseTransport)
@@ -0,0 +1,30 @@
1
+ from sys import version_info
2
+
3
+ from pyxcp.utils import PYTHON_VERSION, flatten, getPythonVersion, hexDump, slicer
4
+
5
+
6
+ def test_hexdump(capsys):
7
+ print(hexDump(range(16)), end="")
8
+ captured = capsys.readouterr()
9
+ assert captured.out == "[00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f]"
10
+
11
+
12
+ def test_slicer1():
13
+ res = slicer([1, 2, 3, 4, 5, 6, 7, 8], 4)
14
+ assert res == [[1, 2, 3, 4], [5, 6, 7, 8]]
15
+
16
+
17
+ def test_slicer2():
18
+ res = slicer(["10", "20", "30", "40", "50", "60", "70", "80"], 4, tuple)
19
+ assert res == [("10", "20", "30", "40"), ("50", "60", "70", "80")]
20
+
21
+
22
+ def test_flatten1():
23
+ res = flatten([[1, 2, 3, 4], [5, 6, 7, 8]])
24
+ assert res == [1, 2, 3, 4, 5, 6, 7, 8]
25
+
26
+
27
+ def test_version():
28
+ assert getPythonVersion() == version_info
29
+ assert PYTHON_VERSION == version_info
30
+ assert getPythonVersion() == PYTHON_VERSION
pyxcp/timing.py ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env python
2
+ import time
3
+
4
+
5
+ class Timing:
6
+ T_US = 1000 * 1000
7
+ T_MS = 1000
8
+ T_S = 1
9
+
10
+ UNIT_MAP = {
11
+ T_US: "uS",
12
+ T_MS: "mS",
13
+ T_S: "S",
14
+ }
15
+ FMT = "min: {0:2.3f} {4}\nmax: {1:2.3f} {4}\navg: {2:2.3f} {4}\nlast: {3:2.3f} {4}"
16
+
17
+ def __init__(self, unit=T_MS, record=False):
18
+ self.min = None
19
+ self.max = None
20
+ self.avg = None
21
+ self._previous = None
22
+ self.unit = unit
23
+ self._record = record
24
+ self._values = []
25
+
26
+ def start(self):
27
+ self._start = time.perf_counter()
28
+
29
+ def stop(self):
30
+ self._stop = time.perf_counter()
31
+ elapsed = self._stop - self._start
32
+ if self._record:
33
+ self._values.append(elapsed)
34
+ if self._previous:
35
+ self.min = min(self._previous, elapsed)
36
+ self.max = max(self._previous, elapsed)
37
+ self.avg = (self._previous + elapsed) / 2
38
+ else:
39
+ self.min = self.max = self.avg = elapsed
40
+ self._previous = elapsed
41
+
42
+ def __str__(self):
43
+ unitName = Timing.UNIT_MAP.get(self.unit, "??")
44
+ self.min = 0 if self.min is None else self.min
45
+ self.max = 0 if self.max is None else self.max
46
+ self.avg = 0 if self.avg is None else self.avg
47
+ self._previous = 0 if self._previous is None else self._previous
48
+ return Timing.FMT.format(
49
+ self.min * self.unit,
50
+ self.max * self.unit,
51
+ self.avg * self.unit,
52
+ self._previous * self.unit,
53
+ unitName,
54
+ )
55
+
56
+ __repr__ = __str__
57
+
58
+ @property
59
+ def values(self):
60
+ return self._values
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env python
2
+ # from .transport_ext import (
3
+ # FrameAcquisitionPolicy, # noqa: F401
4
+ # FrameRecorderPolicy, # noqa: F401
5
+ # LegacyFrameAcquisitionPolicy, # noqa: F401
6
+ # NoOpPolicy, # noqa: F401
7
+ # StdoutPolicy, # noqa: F401
8
+ # )
9
+
10
+ from .can import Can # noqa: F401
11
+ from .eth import Eth # noqa: F401
12
+ from .sxi import SxI # noqa: F401
13
+ from .usb_transport import Usb # noqa: F401