robotframework-qconnect-base 1.2.2__tar.gz → 1.3.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.
- {robotframework_qconnect_base-1.2.2/robotframework_qconnect_base.egg-info → robotframework_qconnect_base-1.3.0}/PKG-INFO +1 -1
- robotframework_qconnect_base-1.3.0/QConnectBase/QConnectBase.pdf +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/connection_base.py +18 -3
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/connection_manager.py +41 -3
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/qlogger.py +3 -1
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/serialclient/serial_base.py +1 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/raw/raw_tcp.py +2 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/ssh/ssh_client.py +12 -1
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/version.py +2 -2
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0/robotframework_qconnect_base.egg-info}/PKG-INFO +1 -1
- robotframework_qconnect_base-1.2.2/QConnectBase/QConnectBase.pdf +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/LICENSE +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/constants.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/message/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/message/rabbitmq_client.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/serialclient/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/raw/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/ssh/__init__.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/tcp/tcp_base.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/utils.py +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/README.rst +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/robotframework_qconnect_base.egg-info/SOURCES.txt +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/robotframework_qconnect_base.egg-info/dependency_links.txt +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/robotframework_qconnect_base.egg-info/requires.txt +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/robotframework_qconnect_base.egg-info/top_level.txt +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/setup.cfg +0 -0
- {robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: robotframework-qconnect-base
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Robot Framework test library for TCP, SSH, serial connection
|
|
5
5
|
Home-page: https://github.com/test-fullautomation/robotframework-qconnect-base
|
|
6
6
|
Author: Nguyen Huynh Tri Cuong
|
|
Binary file
|
|
@@ -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
|
-
|
|
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):
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
{robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/qlogger.py
RENAMED
|
@@ -163,6 +163,7 @@ Check if the connection config is supported by this handler.
|
|
|
163
163
|
return isinstance(config.logfile, str) and \
|
|
164
164
|
config.logfile != 'nonlog' and \
|
|
165
165
|
config.logfile != 'console' and \
|
|
166
|
+
config.logfile != '' and \
|
|
166
167
|
config.logfile != constants.DEFAULT_LOGGER
|
|
167
168
|
|
|
168
169
|
|
|
@@ -250,7 +251,8 @@ Check if the connection config is supported by this handler.
|
|
|
250
251
|
False if the config is not supported.
|
|
251
252
|
"""
|
|
252
253
|
return (isinstance(config.logfile, bool) and config.logfile) or \
|
|
253
|
-
config.logfile == constants.DEFAULT_LOGGER
|
|
254
|
+
config.logfile == constants.DEFAULT_LOGGER or \
|
|
255
|
+
config.logfile == ''
|
|
254
256
|
|
|
255
257
|
|
|
256
258
|
class QConsoleHandler(logging.StreamHandler):
|
|
@@ -92,6 +92,7 @@ class RawTCPServer(TCPBaseServer, RawTCPBase):
|
|
|
92
92
|
Class for a raw tcp connection server.
|
|
93
93
|
"""
|
|
94
94
|
_CONNECTION_TYPE = "TCPIPServer"
|
|
95
|
+
ACCEPT_VERIFY_PARAMS = []
|
|
95
96
|
|
|
96
97
|
def __init__(self, mode=None, config=None):
|
|
97
98
|
"""
|
|
@@ -120,6 +121,7 @@ class RawTCPClient(TCPBaseClient, RawTCPBase):
|
|
|
120
121
|
Class for a raw tcp connection client.
|
|
121
122
|
"""
|
|
122
123
|
_CONNECTION_TYPE = "TCPIPClient"
|
|
124
|
+
ACCEPT_VERIFY_PARAMS = []
|
|
123
125
|
|
|
124
126
|
def __init__(self, mode=None, config=None):
|
|
125
127
|
"""
|
|
@@ -55,6 +55,8 @@ Class to store the configuration for SSH connection.
|
|
|
55
55
|
password = ''
|
|
56
56
|
authentication = 'password'
|
|
57
57
|
key_filename = None
|
|
58
|
+
prompt_regex = r'[#$>] ?$'
|
|
59
|
+
timeout = 10
|
|
58
60
|
|
|
59
61
|
|
|
60
62
|
class SSHClient(TCPBase, TCPBaseClient):
|
|
@@ -62,6 +64,7 @@ class SSHClient(TCPBase, TCPBaseClient):
|
|
|
62
64
|
SSH client connection class.
|
|
63
65
|
"""
|
|
64
66
|
_CONNECTION_TYPE = "SSHClient"
|
|
67
|
+
ACCEPT_VERIFY_PARAMS = []
|
|
65
68
|
|
|
66
69
|
def __init__(self, _mode, config):
|
|
67
70
|
"""
|
|
@@ -86,6 +89,7 @@ Constructor for SSHClient class.
|
|
|
86
89
|
self._llrecv_thrd_obj = None
|
|
87
90
|
self.chan = None
|
|
88
91
|
self.client = None
|
|
92
|
+
self.shell_ready = threading.Event()
|
|
89
93
|
|
|
90
94
|
self.config = SSHConfig(**config)
|
|
91
95
|
config_tcp = {
|
|
@@ -98,6 +102,8 @@ Constructor for SSHClient class.
|
|
|
98
102
|
self._password = self.config.password
|
|
99
103
|
self._key_filename = self.config.key_filename
|
|
100
104
|
self._authentication = self.config.authentication
|
|
105
|
+
self._conn_timeout = getattr(self.config, 'timeout', 10)
|
|
106
|
+
self._prompt_regex = re.compile(getattr(self.config, 'prompt_regex', r'[#$>] ?$'))
|
|
101
107
|
|
|
102
108
|
# create the queue for this connection
|
|
103
109
|
self.SSHq = queue.Queue()
|
|
@@ -132,6 +138,10 @@ Implementation the thread for getting data from ssh connection.
|
|
|
132
138
|
for character in data:
|
|
133
139
|
self.SSHq.put(character)
|
|
134
140
|
|
|
141
|
+
if not self.shell_ready.is_set():
|
|
142
|
+
if self._prompt_regex.search(data):
|
|
143
|
+
self.shell_ready.set()
|
|
144
|
+
|
|
135
145
|
if self.chan.closed is True:
|
|
136
146
|
break
|
|
137
147
|
|
|
@@ -219,7 +229,8 @@ Implementation for creating a SSH connection.
|
|
|
219
229
|
# Therefore we need to open a shell.
|
|
220
230
|
self.chan = self.client.invoke_shell()
|
|
221
231
|
BuiltIn().log("%s: successfully invoked SSH shell for secure communication." % _mident, constants.LOG_LEVEL_DEBUG)
|
|
222
|
-
|
|
232
|
+
if not self.shell_ready.wait(timeout=self._conn_timeout):
|
|
233
|
+
raise TimeoutError(f"Shell prompt is not ready within {self._conn_timeout} seconds after invoking shell.")
|
|
223
234
|
# switch echo off for this terminal
|
|
224
235
|
# echo disturbs when the command contains part of the exepcted reponse, then regexp filtering will
|
|
225
236
|
# fetch the command instead of the response.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: robotframework-qconnect-base
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Robot Framework test library for TCP, SSH, serial connection
|
|
5
5
|
Home-page: https://github.com/test-fullautomation/robotframework-qconnect-base
|
|
6
6
|
Author: Nguyen Huynh Tri Cuong
|
|
Binary file
|
|
File without changes
|
{robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/__init__.py
RENAMED
|
File without changes
|
{robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{robotframework_qconnect_base-1.2.2 → robotframework_qconnect_base-1.3.0}/QConnectBase/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|