robotframework-qconnect-base 1.2.2__tar.gz → 1.4.0__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 (37) hide show
  1. robotframework_qconnect_base-1.4.0/MANIFEST.in +1 -0
  2. robotframework_qconnect_base-1.4.0/PKG-INFO +479 -0
  3. robotframework_qconnect_base-1.4.0/QConnectBase/QConnectBase.pdf +0 -0
  4. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/__init__.py +1 -1
  5. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/connection_base.py +19 -4
  6. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/connection_manager.py +42 -4
  7. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/constants.py +1 -1
  8. robotframework_qconnect_base-1.4.0/QConnectBase/grpc/__init__.py +14 -0
  9. robotframework_qconnect_base-1.4.0/QConnectBase/grpc/grpc_client.py +673 -0
  10. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/message/__init__.py +1 -1
  11. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/message/rabbitmq_client.py +72 -79
  12. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/qlogger.py +4 -2
  13. {robotframework_qconnect_base-1.2.2/QConnectBase/tcp/ssh → robotframework_qconnect_base-1.4.0/QConnectBase/serialclient}/__init__.py +1 -1
  14. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/serialclient/serial_base.py +2 -1
  15. {robotframework_qconnect_base-1.2.2/QConnectBase/serialclient → robotframework_qconnect_base-1.4.0/QConnectBase/tcp}/__init__.py +1 -1
  16. {robotframework_qconnect_base-1.2.2/QConnectBase/tcp → robotframework_qconnect_base-1.4.0/QConnectBase/tcp/raw}/__init__.py +1 -1
  17. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/tcp/raw/raw_tcp.py +3 -1
  18. {robotframework_qconnect_base-1.2.2/QConnectBase/tcp/raw → robotframework_qconnect_base-1.4.0/QConnectBase/tcp/ssh}/__init__.py +1 -1
  19. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/tcp/ssh/ssh_client.py +13 -2
  20. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/tcp/tcp_base.py +1 -1
  21. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/utils.py +1 -1
  22. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/QConnectBase/version.py +3 -3
  23. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/README.rst +62 -44
  24. robotframework_qconnect_base-1.4.0/build_backend.py +97 -0
  25. robotframework_qconnect_base-1.4.0/pyproject.toml +131 -0
  26. robotframework_qconnect_base-1.4.0/robotframework_qconnect_base.egg-info/PKG-INFO +479 -0
  27. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/robotframework_qconnect_base.egg-info/SOURCES.txt +5 -1
  28. robotframework_qconnect_base-1.4.0/robotframework_qconnect_base.egg-info/requires.txt +13 -0
  29. robotframework_qconnect_base-1.2.2/PKG-INFO +0 -472
  30. robotframework_qconnect_base-1.2.2/QConnectBase/QConnectBase.pdf +0 -0
  31. robotframework_qconnect_base-1.2.2/robotframework_qconnect_base.egg-info/PKG-INFO +0 -472
  32. robotframework_qconnect_base-1.2.2/robotframework_qconnect_base.egg-info/requires.txt +0 -3
  33. robotframework_qconnect_base-1.2.2/setup.py +0 -229
  34. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/LICENSE +0 -0
  35. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/robotframework_qconnect_base.egg-info/dependency_links.txt +0 -0
  36. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/robotframework_qconnect_base.egg-info/top_level.txt +0 -0
  37. {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.4.0}/setup.cfg +0 -0
@@ -0,0 +1 @@
1
+ include build_backend.py
@@ -0,0 +1,479 @@
1
+ Metadata-Version: 2.4
2
+ Name: robotframework-qconnect-base
3
+ Version: 1.4.0
4
+ Summary: Robot Framework library for TCP, SSH, serial connection
5
+ Author-email: Nguyen Huynh Tri Cuong <cuong.nguyenhuynhtri@vn.bosch.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://pypi.org/project/robotframework-qconnect-base/
8
+ Project-URL: Documentation, https://github.com/test-fullautomation/robotframework-qconnect-base/blob/develop/QConnectBase/QConnectBase.pdf
9
+ Project-URL: Readme, https://github.com/test-fullautomation/robotframework-qconnect-base/blob/develop/README.rst
10
+ Project-URL: Repository, https://github.com/test-fullautomation/robotframework-qconnect-base
11
+ Project-URL: Issues, https://github.com/test-fullautomation/robotframework-qconnect-base/issues
12
+ Keywords: robotframework,connect,queued,TCP,SSH,serial
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Topic :: Software Development
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/x-rst
20
+ License-File: LICENSE
21
+ Requires-Dist: robotframework>=6.1
22
+ Requires-Dist: robotframework-pythonlibcore
23
+ Requires-Dist: paramiko
24
+ Requires-Dist: pyserial
25
+ Requires-Dist: GenPackageDoc
26
+ Requires-Dist: PythonExtensionsCollection
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=6.0; extra == "dev"
29
+ Requires-Dist: pytest-cov>=3.0; extra == "dev"
30
+ Provides-Extra: docs
31
+ Requires-Dist: docutils>=0.22.4; extra == "docs"
32
+ Dynamic: license-file
33
+
34
+ .. Copyright 2020-2026 Robert Bosch GmbH
35
+
36
+ .. Licensed under the Apache License, Version 2.0 (the "License");
37
+ you may not use this file except in compliance with the License.
38
+ You may obtain a copy of the License at
39
+
40
+ .. http://www.apache.org/licenses/LICENSE-2.0
41
+
42
+ .. Unless required by applicable law or agreed to in writing, software
43
+ distributed under the License is distributed on an "AS IS" BASIS,
44
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45
+ See the License for the specific language governing permissions and
46
+ limitations under the License.
47
+
48
+ Package Description
49
+ ===================
50
+
51
+ Table of Contents
52
+ -----------------
53
+
54
+ - `Getting Started <#getting-started>`__
55
+
56
+ - `How to install <#how-to-install>`__
57
+ - `Usage <#building-and-testing>`__
58
+ - `Example <#example>`__
59
+ - `Contribution Guidelines <#contribution-guidelines>`__
60
+ - `Configure Git and correct EOL
61
+ handling <#configure-Git-and-correct-EOL-handling>`__
62
+ - `Sourcecode Documentation <#documentation>`__
63
+ - `Feedback <#feedback>`__
64
+ - `About <#about>`__
65
+
66
+ - `Maintainers <#maintainers>`__
67
+ - `Contributors <#contributors>`__
68
+ - `3rd Party Licenses <#3rd-party-licenses>`__
69
+ - `Used Encryption <#used-encryption>`__
70
+ - `License <#license>`__
71
+
72
+ Getting Started
73
+ ---------------
74
+
75
+ **QConnectBase** is a library that enables `Robot Framework <https://robotframework.org>`__
76
+ to establish and manage connections to external systems.
77
+
78
+ **QConnectBase** provides a mechanism for continuously receiving trace logs from a connection (such as Raw TCP,
79
+ SSH, Serial, etc.) while sending data back to the remote side. It's especially efficient for monitoring
80
+ overflood response trace logs from asynchronous trace systems.
81
+ It supports Python 3.7+ and Robot Framework 6.1+.
82
+
83
+ How to install
84
+ --------------
85
+
86
+ **QConnectBase** can be installed in two different ways.
87
+
88
+ 1. Installation via PyPi (recommended for users)
89
+
90
+ .. code::
91
+
92
+ pip install robotframework-qconnect-base
93
+
94
+ `QConnectBase in PyPi <https://pypi.org/project/robotframework-qconnect-base/>`_
95
+
96
+ 2. Installation via GitHub (recommended for developers)
97
+
98
+ * Clone the **robotframework-qconnect-base** repository to your machine.
99
+
100
+ .. code::
101
+
102
+ git clone https://github.com/test-fullautomation/robotframework-qconnect-base.git
103
+
104
+ `QConnectBase in GitHub <https://github.com/test-fullautomation/robotframework-qconnect-base>`_
105
+
106
+ * Use the following command to install **QConnectBase** (executed in repository main folder):
107
+
108
+ .. code::
109
+
110
+ python -m pip install .
111
+
112
+ Or:
113
+
114
+ .. code::
115
+
116
+ python -m pip install --proxy <proxy> .
117
+
118
+ This command will also download and install all dependencies that are required to work with the source files in the current repository.
119
+ After the initial installation of **QConnectBase** is done, you have the following two possibilities:
120
+
121
+ 1. *Clean the previous installation*:
122
+
123
+ .. code::
124
+
125
+ python "./cleanup_installation.py"
126
+
127
+ ``cleanup_installation.py`` explicitly deletes all files and folders within the component installation folder under
128
+ ``site-packages`` and also deletes local build artefacts.
129
+
130
+ 2. *Render the component documentation*:
131
+
132
+ .. code::
133
+
134
+ python "./genpackagedoc.py"
135
+
136
+ This would e.g. be required in case of changes in the interface of **QConnectBase**.
137
+
138
+ The documentation is rendered by a separate application called **GenPackageDoc**, that is part
139
+ of the build dependencies and runtime dependencies of **QConnectBase**.
140
+
141
+ **GenPackageDoc** needs to be configured. Details about how to do this, can be found in the
142
+ `README.rst <https://github.com/test-fullautomation/python-genpackagedoc/blob/develop/README.rst>`_
143
+ (sections *Install dependencies* and *Configure dependencies*).
144
+
145
+ * Use the following command to build **QConnectBase** (executed in repository main folder):
146
+
147
+ .. code::
148
+
149
+ python -m build .
150
+
151
+ Or:
152
+
153
+ .. code::
154
+
155
+ python -m pip config set global.proxy <proxy>
156
+ python -m build .
157
+
158
+
159
+ Usage
160
+ -----
161
+
162
+ **QConnectBase** supports the following Robot Framework keywords to establish and manage connections to external systems:
163
+
164
+ **connect**
165
+ ~~~~~~~~~~~
166
+
167
+ **Establishes a connection.**
168
+
169
+ **Syntax**:
170
+
171
+ **connect** ``[conn_name] [conn_conf]``
172
+ *(All parameters are required to be in order)*\
173
+
174
+ or
175
+
176
+ **connect**
177
+ ``conn_name=[conn_name] conn_conf=[conn_conf]``
178
+ *(All parameters are assigned by name)*
179
+
180
+ **Note**: Although previous syntax with 4 arguments is still supported for backward compatibility, only **conn_name** and **conn_conf** are now required.
181
+ **conn_type** and **conn_mode** can be provided inside **conn_conf**.
182
+
183
+ **Arguments**:
184
+
185
+ **conn_name**: Name of the connection.
186
+
187
+ **conn_conf**: A dictionary containing configurations for the connection.
188
+
189
+ It must include **conn_type**, and optionally **conn_mode** and other connection-specific fields (depending on type).
190
+
191
+ This replaces the need to pass **conn_type** and **conn_mode** as separate arguments.
192
+
193
+ Each **conn_type** requires a specific structure in **conn_conf**. Below are examples for each supported type:
194
+
195
+ * **TCPIPClient**: Create a Raw TCPIP connection to TCP Server.
196
+
197
+ ::
198
+
199
+ {
200
+ "conn_type": "TCPIPClient",
201
+ "address": [server host], # Optional. Default value is "localhost".
202
+ "port": [server port], # Optional. Default value is 1234.
203
+ "logfile": [Log file path. Possible values: 'nonlog', 'console', <user define path>]
204
+ }
205
+
206
+ * **SSHClient**: Create a client connection to a SSH server.
207
+
208
+ ::
209
+
210
+ {
211
+ "conn_type": "SSHClient",
212
+ "address" : [server host], # Optional. Default value is "localhost".
213
+ "port" : [server host], # Optional. Default value is 22.
214
+ "username" : [username], # Optional. Default value is "root".
215
+ "password" : [password], # Optional. Default value is "".
216
+ "authentication" : "password" | "keyfile" | "passwordkeyfile", # Optional. Default value is "".
217
+ "key_filename" : [filename or list of filenames], # Optional. Default value is null.
218
+ "logfile": [Log file path. Possible values: 'nonlog', 'console', <user define path>]
219
+ }
220
+
221
+ * **SerialClient**: Create a client connection via Serial Port.
222
+
223
+ ::
224
+
225
+ {
226
+ "conn_type": "SerialClient",
227
+ "port" : [comport or null],
228
+ "baudrate" : [Baud rate such as 9600 or 115200 etc.],
229
+ "bytesize" : [Number of data bits. Possible values: 5, 6, 7, 8],
230
+ "stopbits" : [Number of stop bits. Possible values: 1, 1.5, 2],
231
+ "parity" : [Enable parity checking. Possible values: 'N', 'E', 'O', 'M', 'S'],
232
+ "rtscts" : [Enable hardware (RTS/CTS) flow control.],
233
+ "xonxoff" : [Enable software flow control.],
234
+ "logfile": [Log file path. Possible values: 'nonlog', 'console', <user define path>]
235
+ }
236
+
237
+ **Legacy Syntax** (Still Supported):
238
+
239
+ **connect** ``[conn_name] [conn_type] [conn_conf] [conn_mode]``
240
+ *(All parameters are required to be in order)*\
241
+
242
+ or
243
+
244
+ **connect**
245
+ ``conn_name=[conn_name] conn_type=[conn_type] conn_conf=[conn_conf] conn_mode=[conn_mode]``
246
+ *(All parameters are assigned by name)*
247
+
248
+
249
+ **disconnect**
250
+ ~~~~~~~~~~~~~~
251
+
252
+ **Disconnects a connection by name.**
253
+
254
+ **Syntax**:
255
+
256
+ **disconnect** ``conn_name``
257
+
258
+ **Arguments**:
259
+
260
+ **conn_name**: Name of the connection.
261
+
262
+ **send command**
263
+ ~~~~~~~~~~~~~~~~
264
+
265
+ **Sends a command to the other side of the connection.**
266
+
267
+ **Syntax**:
268
+
269
+ **send command** ``[conn_name] [command]`` *(All parameters are
270
+ required to be in order)*\
271
+
272
+ or
273
+
274
+ **send command**
275
+ ``conn_name=[conn_name] command=[command]`` *(All parameters are
276
+ assigned by name)*
277
+
278
+ **Arguments**:
279
+
280
+ **conn_name**: Name of the connection.
281
+
282
+ **command**: Command to be sent.
283
+
284
+ **verify**
285
+ ~~~~~~~~~~
286
+
287
+ **Verifies a response from the connection if it matched a pattern.**
288
+
289
+ **Syntax**:
290
+
291
+ **verify**
292
+ ``[conn_name] [search_pattern] [timeout] [fetch_block] [eob_pattern] [filter_pattern] [send_cmd]``\ *(All
293
+ parameters are required to be in order)*\
294
+
295
+ or
296
+
297
+ **verify** ``conn_name=[conn_name] search_pattern=[search_pattern] timeout=[timeout] fetch_block=[fetch_block] eob_pattern=[eob_pattern] filter_pattern=[filter_pattern] send_cmd=[send_cmd]``
298
+ *(All parameters are assigned by name)*
299
+
300
+ **Arguments**:
301
+
302
+ **conn_name**: Name of the connection.
303
+
304
+ **search_pattern**: Regular expression for matching with the response.
305
+
306
+ **timeout**: Timeout for waiting response matching pattern.
307
+
308
+ **fetch_block**: If this value is true, every response line will be put into a block untill a line match **eob_pattern** pattern.
309
+
310
+ **eob_pattern**: Regular expression for matching the endline when using **fetch_block**.
311
+
312
+ **filter_pattern**: Regular expression for filtering every line of block when using **fetch_block**.
313
+
314
+ **send_cmd**: Command to be sent to the other side of connection and waiting for response.
315
+
316
+ **Return value**:
317
+
318
+ **List of captured string from search_pattern**
319
+
320
+ **E.g.**
321
+ The message from connection is **This is the 1st test command.**
322
+
323
+ The `verify` keyword of RobotFramework test case is defined as below:
324
+
325
+ ::
326
+
327
+ ${result} = verify conn_name=SSH_Connection
328
+ search_pattern=(?<=\s).*([0-9]..).*(command).$
329
+ send_cmd=*echo This is the 1st test command.*
330
+
331
+ The result will be a list of 2 strings:
332
+
333
+ - **${result}[0]** will be **"1st"** which is the first captured string.
334
+ - **${result}[1]** will be **"command"** which is the second captured string.
335
+
336
+ Example
337
+ -------
338
+
339
+ ::
340
+
341
+ *** Settings ***
342
+ Documentation Suite description
343
+ Library QConnectBase.ConnectionManager
344
+
345
+ *** Test Cases ***
346
+ Test SSH Connection
347
+ # Create config for connection.
348
+ ${config_string}= catenate
349
+ ... {
350
+ ... "address": "127.0.0.1",
351
+ ... "port": 8022,
352
+ ... "username": "root",
353
+ ... "password": "",
354
+ ... "authentication": "password",
355
+ ... "key_filename": null
356
+ ... }
357
+ log to console \nConnecting with configurations:\n${config_string}
358
+ ${config}= evaluate json.loads('''${config_string}''') json
359
+
360
+ # Connect to the target with above configurations.
361
+ connect conn_name=test_ssh
362
+ ... conn_type=SSHClient
363
+ ... conn_conf=${config}
364
+
365
+ # Send command 'cd ..' and 'ls' then wait for the response '.*' pattern.
366
+ send command conn_name=test_ssh
367
+ ... command=cd ..
368
+
369
+ ${res}= verify conn_name=test_ssh
370
+ ... search_pattern=.*
371
+ ... send_cmd=ls
372
+ log to console ${res}
373
+
374
+ # Disconnect
375
+ disconnect test_ssh
376
+
377
+ Contribution Guidelines
378
+ -----------------------
379
+
380
+ **QConnectBase** is designed for ease of making an extension library. By that way you can take advantage of the
381
+ infrastructure of **QConnectBase** for handling your own connection protocol. For creating an extension library
382
+ for **QConnectBase**, please following below steps.
383
+
384
+ 1. Create a library package which have the prefix name is **robotframework-qconnect-**\ *[your specific name]*.
385
+
386
+ 2. Your hadling connection class should be derived from **QConnectBase.connection_base.ConnectionBase** class.
387
+
388
+ 3. In your *Connection Class*, override below attributes and methods:
389
+
390
+ - **_CONNECTION_TYPE**: name of your connection type. It will be the input of the conn\_type argument when using **connect** keyword. Depend on the type name, the library will detemine the correct connection handling class.
391
+
392
+ - **__init__(self, \_mode, config)**: in this constructor method, you should:
393
+
394
+ - Prepare resource for your connection.
395
+ - Initialize receiver thread by calling **self._init_thread_receiver(cls._socket_instance, mode="")** method.
396
+ - Configure and initialize the lowlevel receiver thread (if it’s necessary) as below
397
+
398
+ ::
399
+
400
+ self._llrecv_thrd_obj = None
401
+ self._llrecv_thrd_term = threading.Event()
402
+ self._init_thrd_llrecv(cls._socket_instance)
403
+
404
+
405
+ - Incase you use the lowlevel receiver thread. You should implement the **thrd_llrecv_from_connection_interface()** method. This method is a mediate layer which will receive the data from connection at the very beginning, do some process then put them in a queue for the **receiver thread** above getting later.
406
+ - Create the queue for this connection (use Queue.Queue).
407
+
408
+ - **connect()**: implement the way you use to make your own connection protocol.
409
+ - **_read()**: implement the way to receive data from connection.
410
+ - **_write()**: implement the way to send data via connection.
411
+ - **disconnect()**: implement the way you use to disconnect your own connection protocol.
412
+ - **quit()**: implement the way you use to quit connection and clean resource.
413
+
414
+ Configure Git and correct EOL handling
415
+ --------------------------------------
416
+
417
+ Here you can find the references for `Dealing with line
418
+ endings <https://help.github.com/articles/dealing-with-line-endings/>`__.
419
+
420
+ Every time you press return on your keyboard you’re actually inserting
421
+ an invisible character called a line ending. Historically, different
422
+ operating systems have handled line endings differently. When you view
423
+ changes in a file, Git handles line endings in its own way. Since you’re
424
+ collaborating on projects with Git and GitHub, Git might produce
425
+ unexpected results if, for example, you’re working on a Windows machine,
426
+ and your collaborator has made a change in OS X.
427
+
428
+ To avoid problems in your diffs, you can configure Git to properly
429
+ handle line endings. If you are storing the .gitattributes file directly
430
+ inside of your repository, than you can asure that all EOL are manged by
431
+ git correctly as defined.
432
+
433
+ Sourcecode Documentation
434
+ ------------------------
435
+
436
+ A detailed documentation of the QConnectBase package can also be found here: `QConnectBase.pdf <https://github.com/test-fullautomation/robotframework-qconnect-base/blob/develop/QConnectBase/QConnectBase.pdf>`_
437
+
438
+ Feedback
439
+ --------
440
+
441
+ If you have any problem when using the library or think there is a
442
+ better solution for any part of the library, I’d love to know it, as
443
+ this will all help me to improve the library. Please don't hesitate
444
+ to contact me.
445
+
446
+ Do share your valuable opinion, I appreciate your honest feedback!
447
+
448
+ About
449
+ -----
450
+
451
+ Maintainers
452
+ ~~~~~~~~~~~
453
+
454
+ `Nguyen Huynh Tri Cuong <mailto:Cuong.NguyenHuynhTri@vn.bosch.com>`_
455
+
456
+ Contributors
457
+ ~~~~~~~~~~~~
458
+
459
+ `Nguyen Huynh Tri Cuong <mailto:Cuong.NguyenHuynhTri@vn.bosch.com>`_
460
+
461
+ `Thomas Pollerspöck <mailto:Thomas.Pollerspoeck@de.bosch.com>`_
462
+
463
+
464
+ License
465
+ -------
466
+
467
+ Copyright 2020-2026 Robert Bosch GmbH
468
+
469
+ Licensed under the Apache License, Version 2.0 (the "License");
470
+ you may not use this file except in compliance with the License.
471
+ You may obtain a copy of the License at
472
+
473
+ http://www.apache.org/licenses/LICENSE-2.0
474
+
475
+ Unless required by applicable law or agreed to in writing, software
476
+ distributed under the License is distributed on an "AS IS" BASIS,
477
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
478
+ See the License for the specific language governing permissions and
479
+ limitations under the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Robert Bosch GmbH
1
+ # Copyright 2020-2026 Robert Bosch GmbH
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Robert Bosch GmbH
1
+ # Copyright 2020-2026 Robert Bosch GmbH
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -46,6 +46,11 @@ _platform = platform.system().lower()
46
46
  class BrokenConnError(Exception):
47
47
  pass
48
48
 
49
+ class EndOfBlockNotFound(Exception):
50
+ pass
51
+
52
+ class NoFilteredMsgFound(Exception):
53
+ pass
49
54
 
50
55
  class ConnectionBase(object):
51
56
  """
@@ -61,6 +66,8 @@ Base class for all connection classes.
61
66
 
62
67
  RECV_MSGS_POLLING_INTERVAL = 0.005
63
68
 
69
+ ACCEPT_VERIFY_PARAMS = None
70
+
64
71
  _call_thrd_obj = None
65
72
  _call_thrd_init = threading.Event()
66
73
  _call_thrd_term = threading.Event()
@@ -398,14 +405,14 @@ Thread to receive data from connection continuously.
398
405
  else:
399
406
  if matchObj is not None:
400
407
  back_trace_queue.append(msg)
401
- (is_hit, result_obj) = self._filter_msg(regex_filter, "\n".join(back_trace_queue))
408
+ if len(back_trace_queue):
409
+ (is_hit, result_obj) = self._filter_msg(regex_filter, "\r\n".join(back_trace_queue))
402
410
  else:
403
411
  (is_hit, result_obj) = self._filter_msg(regex_filter, msg)
404
412
  if is_hit:
405
413
  now = time.time()
406
- if (use_fetch_block is True) and regex_end_block_pattern and (regex_end_block_pattern.pattern != ".*"):
414
+ if (use_fetch_block is True) and regex_end_block_pattern and (regex_end_block_pattern.pattern != ".*") and len(back_trace_queue):
407
415
  result_obj = regex_filter.search("\r\n".join(back_trace_queue))
408
- back_trace_queue.clear()
409
416
  msg_queue.put((now, result_obj), False)
410
417
  self.post_msg_check(msg)
411
418
  except BrokenConnError as reason:
@@ -562,12 +569,20 @@ Suspend the control flow until a Trace message is received which matches to a sp
562
569
  except queue.Empty:
563
570
  success = False
564
571
  finally:
572
+ back_trace_queue = self._traceq_obj[trq_handle][2]
573
+ filtered_line_counter = len(back_trace_queue)
574
+ back_trace_queue.clear()
565
575
  self.deactivate_and_delete_trace_queue(trq_handle, trace_queue)
566
576
 
567
577
  BuiltIn().log('Completed %s' % _mident, constants.LOG_LEVEL_DEBUG)
578
+
579
+ if match is None and filtered_line_counter == 0 and filter_pattern != ".*":
580
+ raise NoFilteredMsgFound()
568
581
  if success:
569
582
  return match
570
583
  else:
584
+ if end_of_block_pattern is not None:
585
+ raise EndOfBlockNotFound()
571
586
  return None
572
587
 
573
588
  def wait_4_trace_continuously(self, trace_queue, timeout=0, *fct_args):
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Robert Bosch GmbH
1
+ # Copyright 2020-2026 Robert Bosch GmbH
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
27
27
  #
28
28
  # *******************************************************************************
29
29
  from QConnectBase.utils import *
30
- from QConnectBase.connection_base import ConnectionBase
30
+ from QConnectBase.connection_base import ConnectionBase, EndOfBlockNotFound, NoFilteredMsgFound
31
31
  from robot.libraries.BuiltIn import BuiltIn
32
32
  from os.path import dirname
33
33
  from QConnectBase.utils import DictToClass
@@ -145,6 +145,31 @@ Constructor for ConnectionManager class.
145
145
  self.ROBOT_LIBRARY_LISTENER = self
146
146
  self.ROBOT_LISTENER_API_VERSION = 3
147
147
 
148
+ def __validate_optional_verify_parameters(self, optional_params, conn_name):
149
+ """
150
+ Validate optional parameters for verify keyword.
151
+
152
+ **Arguments:**
153
+
154
+ * ``optional_params``
155
+
156
+ / *Condition*: required / *Type*: dict /
157
+
158
+ Dictionary of optional parameters
159
+ """
160
+ connection_obj = self.get_connection_by_name(conn_name, raise_exception=True)
161
+ accept_verify_params = getattr(connection_obj, 'ACCEPT_VERIFY_PARAMS', None)
162
+ if accept_verify_params is None:
163
+ return
164
+
165
+ msg_supported_params = ''
166
+ if len(accept_verify_params) > 0:
167
+ msg_supported_params = f" Valid params: {', '.join(accept_verify_params)}"
168
+
169
+ invalid_params = [k for k in optional_params.keys() if k not in accept_verify_params]
170
+ if len(invalid_params) > 0:
171
+ raise Exception(f"Unexpected 'verify' parameter(s) found for '{connection_obj._CONNECTION_TYPE}' connection type: {', '.join(invalid_params)}.{msg_supported_params}")
172
+
148
173
  @staticmethod
149
174
  def import_modules_from_paths(paths):
150
175
  """
@@ -757,6 +782,7 @@ Verify a pattern from connection response after sending a command.
757
782
  - ``${res}[1]`` will be **command**, i.e. the second *captured string* defined in the pattern ``(command)``.
758
783
 
759
784
  """
785
+ self.__validate_optional_verify_parameters(kwargs, conn_name)
760
786
  validate_regex_pattern(search_pattern, 'search_pattern')
761
787
  if timeout is not None and timeout < self.MIN_VERIFY_TIMEOUT:
762
788
  raise Exception(
@@ -794,9 +820,16 @@ Verify a pattern from connection response after sending a command.
794
820
 
795
821
  BuiltIn().log(f"sending command '{send_cmd}' to '{conn_name}' ...", constants.LOG_LEVEL_INFO)
796
822
  res = None
823
+ eob_found = True
824
+ has_filtered_msg = True
797
825
  for i in range(1, match_try+1):
798
826
  kwargs['send_cmd'] = send_cmd
799
- res = connection_obj.wait_4_trace(search_pattern, timeout, fetch_block, eob_pattern, filter_pattern, **kwargs)
827
+ try:
828
+ res = connection_obj.wait_4_trace(search_pattern, timeout, fetch_block, eob_pattern, filter_pattern, **kwargs)
829
+ except EndOfBlockNotFound:
830
+ eob_found = False
831
+ except NoFilteredMsgFound:
832
+ has_filtered_msg = False
800
833
  if res is None:
801
834
  log_level = constants.LOG_LEVEL_WARNING if (i == match_try) else constants.LOG_LEVEL_INFO
802
835
  BuiltIn().log(f"[{conn_name}] Match try {i}/{match_try} timed out ('{search_pattern}')", log_level)
@@ -804,7 +837,12 @@ Verify a pattern from connection response after sending a command.
804
837
  break
805
838
 
806
839
  if not res:
807
- raise AssertionError(f"Failed to match the pattern '{search_pattern}' within '{match_try}' {'try' if match_try == 1 else 'tries'} ({conn_name}).")
840
+ if not eob_found:
841
+ raise AssertionError(f"Failed to match the end of block pattern '{eob_pattern}' within '{match_try}' {'try' if match_try == 1 else 'tries'} ({conn_name}).")
842
+ elif not has_filtered_msg:
843
+ raise AssertionError(f"Failed to receive any message that matches the filter pattern '{filter_pattern}' within '{match_try}' {'try' if match_try == 1 else 'tries'} ({conn_name}).")
844
+ else:
845
+ raise AssertionError(f"Failed to match the pattern '{search_pattern}' within '{match_try}' {'try' if match_try == 1 else 'tries'} ({conn_name}).")
808
846
 
809
847
  # Determine if the pattern has capturing groups
810
848
  has_groups = has_capturing_groups(search_pattern) if search_pattern else False
@@ -1,4 +1,4 @@
1
- # Copyright 2020-2023 Robert Bosch GmbH
1
+ # Copyright 2020-2026 Robert Bosch GmbH
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,14 @@
1
+ # Copyright 2020-2026 Robert Bosch GmbH
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from .grpc_client import *