robotframework-pabot 3.1.0__py3-none-any.whl → 4.0.4__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.
- pabot/SharedLibrary.py +7 -4
- pabot/__init__.py +2 -1
- pabot/arguments.py +94 -94
- pabot/execution_items.py +2 -13
- pabot/pabot.py +72 -31
- pabot/pabotlib.py +7 -7
- pabot/py3/messages.py +0 -1
- {robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/METADATA +1 -1
- robotframework_pabot-4.0.4.dist-info/RECORD +22 -0
- robotframework_pabot-3.1.0.dist-info/RECORD +0 -22
- {robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/LICENSE.txt +0 -0
- {robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/WHEEL +0 -0
- {robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/entry_points.txt +0 -0
- {robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/top_level.txt +0 -0
pabot/SharedLibrary.py
CHANGED
|
@@ -11,7 +11,6 @@ from .robotremoteserver import RemoteLibraryFactory
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class SharedLibrary(object):
|
|
14
|
-
|
|
15
14
|
ROBOT_LIBRARY_SCOPE = "GLOBAL"
|
|
16
15
|
|
|
17
16
|
def __init__(self, name, args=None):
|
|
@@ -26,8 +25,10 @@ class SharedLibrary(object):
|
|
|
26
25
|
"Not currently running pabot. Importing library for this process."
|
|
27
26
|
)
|
|
28
27
|
self._lib = RemoteLibraryFactory(
|
|
29
|
-
TestLibrary.from_name(
|
|
30
|
-
|
|
28
|
+
TestLibrary.from_name(
|
|
29
|
+
name, args=args, variables=None, create_keywords=True
|
|
30
|
+
).instance
|
|
31
|
+
if ROBOT_VERSION >= "7.0"
|
|
31
32
|
else TestLibrary(name, args=args).get_instance()
|
|
32
33
|
)
|
|
33
34
|
return
|
|
@@ -36,7 +37,9 @@ class SharedLibrary(object):
|
|
|
36
37
|
remotelib = Remote(uri) if uri else None
|
|
37
38
|
if remotelib:
|
|
38
39
|
try:
|
|
39
|
-
port = remotelib.run_keyword(
|
|
40
|
+
port = remotelib.run_keyword(
|
|
41
|
+
"import_shared_library", [name], {"args": args}
|
|
42
|
+
)
|
|
40
43
|
except RuntimeError:
|
|
41
44
|
logger.error("No connection - is pabot called with --pabotlib option?")
|
|
42
45
|
raise
|
pabot/__init__.py
CHANGED
pabot/arguments.py
CHANGED
|
@@ -80,7 +80,7 @@ def _parse_pabot_args(args): # type: (List[str]) -> Tuple[List[str], Dict[str,
|
|
|
80
80
|
"verbose": False,
|
|
81
81
|
"help": False,
|
|
82
82
|
"testlevelsplit": False,
|
|
83
|
-
"pabotlib":
|
|
83
|
+
"pabotlib": True,
|
|
84
84
|
"pabotlibhost": "127.0.0.1",
|
|
85
85
|
"pabotlibport": 8270,
|
|
86
86
|
"processes": _processes_count(),
|
|
@@ -91,108 +91,108 @@ def _parse_pabot_args(args): # type: (List[str]) -> Tuple[List[str], Dict[str,
|
|
|
91
91
|
"shardcount": 1,
|
|
92
92
|
"chunk": False,
|
|
93
93
|
}
|
|
94
|
+
# Explicitly define argument types for validation
|
|
95
|
+
flag_args = {
|
|
96
|
+
"verbose",
|
|
97
|
+
"help",
|
|
98
|
+
"testlevelsplit",
|
|
99
|
+
"pabotlib",
|
|
100
|
+
"artifactsinsubfolders",
|
|
101
|
+
"chunk",
|
|
102
|
+
}
|
|
103
|
+
value_args = {
|
|
104
|
+
"hive": str,
|
|
105
|
+
"processes": lambda x: int(x) if x != "all" else None,
|
|
106
|
+
"resourcefile": str,
|
|
107
|
+
"pabotlibhost": str,
|
|
108
|
+
"pabotlibport": int,
|
|
109
|
+
"processtimeout": int,
|
|
110
|
+
"ordering": _parse_ordering,
|
|
111
|
+
"suitesfrom": str,
|
|
112
|
+
"artifacts": lambda x: x.split(","),
|
|
113
|
+
"shard": _parse_shard,
|
|
114
|
+
}
|
|
115
|
+
|
|
94
116
|
argumentfiles = []
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"pabotlibhost",
|
|
108
|
-
"pabotlibport",
|
|
109
|
-
"processtimeout",
|
|
110
|
-
"ordering",
|
|
111
|
-
"suitesfrom",
|
|
112
|
-
"artifacts",
|
|
113
|
-
"artifactsinsubfolders",
|
|
114
|
-
"help",
|
|
115
|
-
"shard",
|
|
116
|
-
"chunk",
|
|
117
|
-
]
|
|
118
|
-
]
|
|
119
|
-
or ARGSMATCHER.match(args[0])
|
|
120
|
-
):
|
|
121
|
-
if args[0] == "--hive":
|
|
122
|
-
pabot_args["hive"] = args[1]
|
|
123
|
-
args = args[2:]
|
|
124
|
-
continue
|
|
125
|
-
if args[0] == "--command":
|
|
126
|
-
end_index = args.index("--end-command")
|
|
127
|
-
pabot_args["command"] = args[1:end_index]
|
|
128
|
-
args = args[end_index + 1 :]
|
|
129
|
-
continue
|
|
130
|
-
if args[0] == "--processes":
|
|
131
|
-
pabot_args["processes"] = int(args[1]) if args[1] != 'all' else None
|
|
132
|
-
args = args[2:]
|
|
133
|
-
continue
|
|
134
|
-
if args[0] == "--verbose":
|
|
135
|
-
pabot_args["verbose"] = True
|
|
136
|
-
args = args[1:]
|
|
137
|
-
continue
|
|
138
|
-
if args[0] == "--chunk":
|
|
139
|
-
pabot_args["chunk"] = True
|
|
140
|
-
args = args[1:]
|
|
141
|
-
continue
|
|
142
|
-
if args[0] == "--resourcefile":
|
|
143
|
-
pabot_args["resourcefile"] = args[1]
|
|
144
|
-
args = args[2:]
|
|
145
|
-
continue
|
|
146
|
-
if args[0] == "--pabotlib":
|
|
147
|
-
pabot_args["pabotlib"] = True
|
|
148
|
-
args = args[1:]
|
|
149
|
-
continue
|
|
150
|
-
if args[0] == "--ordering":
|
|
151
|
-
pabot_args["ordering"] = _parse_ordering(args[1])
|
|
152
|
-
args = args[2:]
|
|
117
|
+
remaining_args = []
|
|
118
|
+
i = 0
|
|
119
|
+
|
|
120
|
+
# Track conflicting options during parsing
|
|
121
|
+
saw_pabotlib_flag = False
|
|
122
|
+
saw_no_pabotlib = False
|
|
123
|
+
|
|
124
|
+
while i < len(args):
|
|
125
|
+
arg = args[i]
|
|
126
|
+
if not arg.startswith("--"):
|
|
127
|
+
remaining_args.append(arg)
|
|
128
|
+
i += 1
|
|
153
129
|
continue
|
|
154
|
-
|
|
155
|
-
|
|
130
|
+
|
|
131
|
+
arg_name = arg[2:] # Strip '--'
|
|
132
|
+
|
|
133
|
+
if arg_name == "no-pabotlib":
|
|
134
|
+
saw_no_pabotlib = True
|
|
135
|
+
pabot_args["pabotlib"] = False # Just set the main flag
|
|
156
136
|
args = args[1:]
|
|
157
137
|
continue
|
|
158
|
-
if
|
|
159
|
-
|
|
160
|
-
args = args[2:]
|
|
161
|
-
continue
|
|
162
|
-
if args[0] == "--pabotlibport":
|
|
163
|
-
pabot_args["pabotlibport"] = int(args[1])
|
|
164
|
-
args = args[2:]
|
|
165
|
-
continue
|
|
166
|
-
if args[0] == "--processtimeout":
|
|
167
|
-
pabot_args["processtimeout"] = int(args[1])
|
|
168
|
-
args = args[2:]
|
|
169
|
-
continue
|
|
170
|
-
if args[0] == "--suitesfrom":
|
|
171
|
-
pabot_args["suitesfrom"] = args[1]
|
|
172
|
-
args = args[2:]
|
|
173
|
-
continue
|
|
174
|
-
if args[0] == "--artifacts":
|
|
175
|
-
pabot_args["artifacts"] = args[1].split(",")
|
|
176
|
-
args = args[2:]
|
|
177
|
-
continue
|
|
178
|
-
if args[0] == "--artifactsinsubfolders":
|
|
179
|
-
pabot_args["artifactsinsubfolders"] = True
|
|
138
|
+
if arg_name == "pabotlib":
|
|
139
|
+
saw_pabotlib_flag = True
|
|
180
140
|
args = args[1:]
|
|
181
141
|
continue
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
142
|
+
|
|
143
|
+
# Special case for command
|
|
144
|
+
if arg_name == "command":
|
|
145
|
+
try:
|
|
146
|
+
end_index = args.index("--end-command", i)
|
|
147
|
+
pabot_args["command"] = args[i + 1 : end_index]
|
|
148
|
+
i = end_index + 1
|
|
149
|
+
continue
|
|
150
|
+
except ValueError:
|
|
151
|
+
raise DataError("--command requires matching --end-command")
|
|
152
|
+
|
|
153
|
+
# Handle flag arguments
|
|
154
|
+
if arg_name in flag_args:
|
|
155
|
+
pabot_args[arg_name] = True
|
|
156
|
+
i += 1
|
|
157
|
+
continue
|
|
158
|
+
|
|
159
|
+
# Handle value arguments
|
|
160
|
+
if arg_name in value_args:
|
|
161
|
+
if i + 1 >= len(args):
|
|
162
|
+
raise DataError(f"--{arg_name} requires a value")
|
|
163
|
+
try:
|
|
164
|
+
value = value_args[arg_name](args[i + 1])
|
|
165
|
+
if arg_name == "shard":
|
|
166
|
+
pabot_args["shardindex"], pabot_args["shardcount"] = value
|
|
167
|
+
elif arg_name == "pabotlibhost":
|
|
168
|
+
pabot_args["pabotlib"] = False
|
|
169
|
+
pabot_args[arg_name] = value
|
|
170
|
+
else:
|
|
171
|
+
pabot_args[arg_name] = value
|
|
172
|
+
i += 2
|
|
173
|
+
continue
|
|
174
|
+
except (ValueError, TypeError) as e:
|
|
175
|
+
raise DataError(f"Invalid value for --{arg_name}: {args[i + 1]}")
|
|
176
|
+
|
|
177
|
+
# Handle argument files
|
|
178
|
+
match = ARGSMATCHER.match(arg)
|
|
187
179
|
if match:
|
|
188
|
-
|
|
189
|
-
|
|
180
|
+
if i + 1 >= len(args):
|
|
181
|
+
raise DataError(f"{arg} requires a value")
|
|
182
|
+
argumentfiles.append((match.group(1), args[i + 1]))
|
|
183
|
+
i += 2
|
|
190
184
|
continue
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
|
|
186
|
+
# If we get here, it's a non-pabot argument
|
|
187
|
+
remaining_args.append(arg)
|
|
188
|
+
i += 1
|
|
189
|
+
|
|
190
|
+
if saw_pabotlib_flag and saw_no_pabotlib:
|
|
191
|
+
raise DataError("Cannot use both --pabotlib and --no-pabotlib options together")
|
|
192
|
+
|
|
194
193
|
pabot_args["argumentfiles"] = argumentfiles
|
|
195
|
-
|
|
194
|
+
|
|
195
|
+
return remaining_args, pabot_args
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
def _parse_ordering(filename): # type: (str) -> List[ExecutionItem]
|
pabot/execution_items.py
CHANGED
|
@@ -8,7 +8,6 @@ from robot.utils import PY2, is_unicode
|
|
|
8
8
|
|
|
9
9
|
@total_ordering
|
|
10
10
|
class ExecutionItem(object):
|
|
11
|
-
|
|
12
11
|
isWait = False
|
|
13
12
|
type = None # type: str
|
|
14
13
|
name = None # type: str
|
|
@@ -51,7 +50,6 @@ class ExecutionItem(object):
|
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
class HivedItem(ExecutionItem):
|
|
54
|
-
|
|
55
53
|
type = "hived"
|
|
56
54
|
|
|
57
55
|
def __init__(self, item, hive):
|
|
@@ -67,7 +65,6 @@ class HivedItem(ExecutionItem):
|
|
|
67
65
|
|
|
68
66
|
|
|
69
67
|
class GroupItem(ExecutionItem):
|
|
70
|
-
|
|
71
68
|
type = "group"
|
|
72
69
|
|
|
73
70
|
def __init__(self):
|
|
@@ -128,7 +125,6 @@ class RunnableItem(ExecutionItem):
|
|
|
128
125
|
|
|
129
126
|
|
|
130
127
|
class SuiteItem(RunnableItem):
|
|
131
|
-
|
|
132
128
|
type = "suite"
|
|
133
129
|
|
|
134
130
|
def __init__(self, name, tests=None, suites=None, dynamictests=None):
|
|
@@ -163,9 +159,9 @@ class SuiteItem(RunnableItem):
|
|
|
163
159
|
return False
|
|
164
160
|
if self.name == other.name:
|
|
165
161
|
return True
|
|
166
|
-
if other.name.endswith(
|
|
162
|
+
if other.name.endswith("." + self.name):
|
|
167
163
|
return True
|
|
168
|
-
if self.name.endswith(
|
|
164
|
+
if self.name.endswith("." + other.name):
|
|
169
165
|
return True
|
|
170
166
|
return False
|
|
171
167
|
|
|
@@ -178,7 +174,6 @@ class SuiteItem(RunnableItem):
|
|
|
178
174
|
|
|
179
175
|
|
|
180
176
|
class TestItem(RunnableItem):
|
|
181
|
-
|
|
182
177
|
type = "test"
|
|
183
178
|
|
|
184
179
|
def __init__(self, name):
|
|
@@ -229,7 +224,6 @@ class DynamicSuiteItem(SuiteItem):
|
|
|
229
224
|
|
|
230
225
|
|
|
231
226
|
class DynamicTestItem(ExecutionItem):
|
|
232
|
-
|
|
233
227
|
type = "dynamictest"
|
|
234
228
|
|
|
235
229
|
def __init__(self, name, suite):
|
|
@@ -258,7 +252,6 @@ class DynamicTestItem(ExecutionItem):
|
|
|
258
252
|
|
|
259
253
|
|
|
260
254
|
class WaitItem(ExecutionItem):
|
|
261
|
-
|
|
262
255
|
type = "wait"
|
|
263
256
|
isWait = True
|
|
264
257
|
|
|
@@ -270,7 +263,6 @@ class WaitItem(ExecutionItem):
|
|
|
270
263
|
|
|
271
264
|
|
|
272
265
|
class GroupStartItem(ExecutionItem):
|
|
273
|
-
|
|
274
266
|
type = "group"
|
|
275
267
|
|
|
276
268
|
def __init__(self):
|
|
@@ -281,7 +273,6 @@ class GroupStartItem(ExecutionItem):
|
|
|
281
273
|
|
|
282
274
|
|
|
283
275
|
class GroupEndItem(ExecutionItem):
|
|
284
|
-
|
|
285
276
|
type = "group"
|
|
286
277
|
|
|
287
278
|
def __init__(self):
|
|
@@ -292,7 +283,6 @@ class GroupEndItem(ExecutionItem):
|
|
|
292
283
|
|
|
293
284
|
|
|
294
285
|
class IncludeItem(ExecutionItem):
|
|
295
|
-
|
|
296
286
|
type = "include"
|
|
297
287
|
|
|
298
288
|
def __init__(self, tag):
|
|
@@ -309,7 +299,6 @@ class IncludeItem(ExecutionItem):
|
|
|
309
299
|
|
|
310
300
|
|
|
311
301
|
class SuiteItems(ExecutionItem):
|
|
312
|
-
|
|
313
302
|
type = "suite"
|
|
314
303
|
|
|
315
304
|
def __init__(self, suites):
|
pabot/pabot.py
CHANGED
|
@@ -44,12 +44,20 @@ options (these must be before normal RF options):
|
|
|
44
44
|
Indicator for a file that can contain shared variables for
|
|
45
45
|
distributing resources.
|
|
46
46
|
|
|
47
|
-
--pabotlib
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
--no-pabotlib
|
|
48
|
+
Disable the PabotLib remote server if you don't need locking or resource distribution features.
|
|
49
|
+
PabotLib remote server is started by default.
|
|
50
50
|
|
|
51
|
-
--pabotlibhost [HOSTNAME]
|
|
52
|
-
|
|
51
|
+
--pabotlibhost [HOSTNAME]
|
|
52
|
+
Connect to an already running instance of the PabotLib remote server at the given host
|
|
53
|
+
(disables the local PabotLib server start). For example, to connect to a
|
|
54
|
+
remote PabotLib server running on another machine:
|
|
55
|
+
|
|
56
|
+
pabot --pabotlibhost 192.168.1.123 --pabotlibport 8271 tests/
|
|
57
|
+
|
|
58
|
+
The remote PabotLib server can be started separately using:
|
|
59
|
+
python -m pabot.pabotlib <path_to_resourcefile> <host> <port>
|
|
60
|
+
python -m pabot.pabotlib resource.txt 192.168.1.123 8271
|
|
53
61
|
|
|
54
62
|
--pabotlibport [PORT]
|
|
55
63
|
Port number of the PabotLib remote server (default is 8270)
|
|
@@ -236,7 +244,7 @@ def execute_and_wait_with(item):
|
|
|
236
244
|
caller_id,
|
|
237
245
|
item.index,
|
|
238
246
|
item.execution_item.type != "test",
|
|
239
|
-
process_timeout=item.timeout
|
|
247
|
+
process_timeout=item.timeout,
|
|
240
248
|
)
|
|
241
249
|
outputxml_preprocessing(
|
|
242
250
|
item.options, outs_dir, name, item.verbose, _make_id(), caller_id
|
|
@@ -294,7 +302,7 @@ def _try_execute_and_wait(
|
|
|
294
302
|
caller_id,
|
|
295
303
|
my_index=-1,
|
|
296
304
|
show_stdout_on_failure=False,
|
|
297
|
-
process_timeout=None
|
|
305
|
+
process_timeout=None,
|
|
298
306
|
):
|
|
299
307
|
# type: (List[str], str, str, bool, int, str, int, bool, Optional[int]) -> None
|
|
300
308
|
plib = None
|
|
@@ -305,7 +313,15 @@ def _try_execute_and_wait(
|
|
|
305
313
|
with open(os.path.join(outs_dir, cmd[0] + "_stdout.out"), "w") as stdout:
|
|
306
314
|
with open(os.path.join(outs_dir, cmd[0] + "_stderr.out"), "w") as stderr:
|
|
307
315
|
process, (rc, elapsed) = _run(
|
|
308
|
-
cmd,
|
|
316
|
+
cmd,
|
|
317
|
+
stderr,
|
|
318
|
+
stdout,
|
|
319
|
+
item_name,
|
|
320
|
+
verbose,
|
|
321
|
+
pool_id,
|
|
322
|
+
my_index,
|
|
323
|
+
outs_dir,
|
|
324
|
+
process_timeout,
|
|
309
325
|
)
|
|
310
326
|
except:
|
|
311
327
|
_write(traceback.format_exc())
|
|
@@ -478,7 +494,17 @@ def _increase_completed(plib, my_index):
|
|
|
478
494
|
)
|
|
479
495
|
|
|
480
496
|
|
|
481
|
-
def _run(
|
|
497
|
+
def _run(
|
|
498
|
+
command,
|
|
499
|
+
stderr,
|
|
500
|
+
stdout,
|
|
501
|
+
item_name,
|
|
502
|
+
verbose,
|
|
503
|
+
pool_id,
|
|
504
|
+
item_index,
|
|
505
|
+
outs_dir,
|
|
506
|
+
process_timeout,
|
|
507
|
+
):
|
|
482
508
|
# type: (List[str], IO[Any], IO[Any], str, bool, int, int, str, Optional[int]) -> Tuple[Union[subprocess.Popen[bytes], subprocess.Popen], Tuple[int, float]]
|
|
483
509
|
timestamp = datetime.datetime.now()
|
|
484
510
|
cmd = " ".join(command)
|
|
@@ -487,10 +513,14 @@ def _run(command, stderr, stdout, item_name, verbose, pool_id, item_index, outs_
|
|
|
487
513
|
# avoid hitting https://bugs.python.org/issue10394
|
|
488
514
|
with POPEN_LOCK:
|
|
489
515
|
my_env = os.environ.copy()
|
|
490
|
-
syslog_file = my_env.get(
|
|
516
|
+
syslog_file = my_env.get("ROBOT_SYSLOG_FILE", None)
|
|
491
517
|
if syslog_file:
|
|
492
|
-
my_env[
|
|
493
|
-
|
|
518
|
+
my_env["ROBOT_SYSLOG_FILE"] = os.path.join(
|
|
519
|
+
outs_dir, os.path.basename(syslog_file)
|
|
520
|
+
)
|
|
521
|
+
process = subprocess.Popen(
|
|
522
|
+
cmd, shell=True, stderr=stderr, stdout=stdout, env=my_env
|
|
523
|
+
)
|
|
494
524
|
if verbose:
|
|
495
525
|
_write_with_id(
|
|
496
526
|
process,
|
|
@@ -507,7 +537,9 @@ def _run(command, stderr, stdout, item_name, verbose, pool_id, item_index, outs_
|
|
|
507
537
|
"EXECUTING %s" % item_name,
|
|
508
538
|
timestamp=timestamp,
|
|
509
539
|
)
|
|
510
|
-
return process, _wait_for_return_code(
|
|
540
|
+
return process, _wait_for_return_code(
|
|
541
|
+
process, item_name, pool_id, item_index, process_timeout
|
|
542
|
+
)
|
|
511
543
|
|
|
512
544
|
|
|
513
545
|
def _wait_for_return_code(process, item_name, pool_id, item_index, process_timeout):
|
|
@@ -522,12 +554,15 @@ def _wait_for_return_code(process, item_name, pool_id, item_index, process_timeo
|
|
|
522
554
|
if process_timeout and elapsed / 10.0 >= process_timeout:
|
|
523
555
|
process.terminate()
|
|
524
556
|
process.wait()
|
|
525
|
-
rc =
|
|
557
|
+
rc = (
|
|
558
|
+
-1
|
|
559
|
+
) # Set a return code indicating that the process was killed due to timeout
|
|
526
560
|
_write_with_id(
|
|
527
561
|
process,
|
|
528
562
|
pool_id,
|
|
529
563
|
item_index,
|
|
530
|
-
"Process %s killed due to exceeding the maximum timeout of %s seconds"
|
|
564
|
+
"Process %s killed due to exceeding the maximum timeout of %s seconds"
|
|
565
|
+
% (item_name, process_timeout),
|
|
531
566
|
)
|
|
532
567
|
break
|
|
533
568
|
|
|
@@ -544,7 +579,6 @@ def _wait_for_return_code(process, item_name, pool_id, item_index, process_timeo
|
|
|
544
579
|
return rc, elapsed / 10.0
|
|
545
580
|
|
|
546
581
|
|
|
547
|
-
|
|
548
582
|
def _read_file(file_handle):
|
|
549
583
|
try:
|
|
550
584
|
with open(file_handle.name, "r") as content_file:
|
|
@@ -1121,7 +1155,6 @@ def store_suite_names(hashes, suite_names):
|
|
|
1121
1155
|
for d in suite_lines
|
|
1122
1156
|
)
|
|
1123
1157
|
except IOError:
|
|
1124
|
-
|
|
1125
1158
|
_write(
|
|
1126
1159
|
"[ "
|
|
1127
1160
|
+ _wrap_with(Color.YELLOW, "WARNING")
|
|
@@ -1154,12 +1187,14 @@ def generate_suite_names_with_builder(outs_dir, datasources, options):
|
|
|
1154
1187
|
# Note: first argument (included_suites) is deprecated from RobotFramework 6.1
|
|
1155
1188
|
if ROBOT_VERSION >= "6.1":
|
|
1156
1189
|
builder = TestSuiteBuilder(
|
|
1157
|
-
included_extensions=settings.extension,
|
|
1190
|
+
included_extensions=settings.extension,
|
|
1191
|
+
rpa=settings.rpa,
|
|
1192
|
+
lang=opts.get("language"),
|
|
1158
1193
|
)
|
|
1159
1194
|
else:
|
|
1160
1195
|
builder = TestSuiteBuilder(
|
|
1161
1196
|
settings["SuiteNames"], settings.extension, rpa=settings.rpa
|
|
1162
|
-
)
|
|
1197
|
+
)
|
|
1163
1198
|
|
|
1164
1199
|
suite = builder.build(*datasources)
|
|
1165
1200
|
settings.rpa = builder.rpa
|
|
@@ -1657,7 +1692,7 @@ class QueueItem(object):
|
|
|
1657
1692
|
argfile,
|
|
1658
1693
|
hive=None,
|
|
1659
1694
|
processes=0,
|
|
1660
|
-
timeout=None
|
|
1695
|
+
timeout=None,
|
|
1661
1696
|
):
|
|
1662
1697
|
# type: (List[str], str, Dict[str, object], ExecutionItem, List[str], bool, Tuple[str, Optional[str]], Optional[str], int, Optional[int]) -> None
|
|
1663
1698
|
self.datasources = datasources
|
|
@@ -1755,7 +1790,7 @@ def _create_items(datasources, opts_for_run, outs_dir, pabot_args, suite_group):
|
|
|
1755
1790
|
argfile,
|
|
1756
1791
|
pabot_args.get("hive"),
|
|
1757
1792
|
pabot_args["processes"],
|
|
1758
|
-
pabot_args["processtimeout"]
|
|
1793
|
+
pabot_args["processtimeout"],
|
|
1759
1794
|
)
|
|
1760
1795
|
for suite in suite_group
|
|
1761
1796
|
for argfile in pabot_args["argumentfiles"] or [("", None)]
|
|
@@ -1774,9 +1809,7 @@ def _create_execution_items_for_dry_run(
|
|
|
1774
1809
|
datasources, opts_for_run, outs_dir, pabot_args, suite_group
|
|
1775
1810
|
)
|
|
1776
1811
|
chunk_size = (
|
|
1777
|
-
round(len(items) / processes_count)
|
|
1778
|
-
if len(items) > processes_count
|
|
1779
|
-
else 1
|
|
1812
|
+
round(len(items) / processes_count) if len(items) > processes_count else 1
|
|
1780
1813
|
)
|
|
1781
1814
|
chunked_items = list(_chunk_items(items, chunk_size))
|
|
1782
1815
|
_NUMBER_OF_ITEMS_TO_BE_EXECUTED += len(chunked_items)
|
|
@@ -1800,7 +1833,7 @@ def _chunk_items(items, chunk_size):
|
|
|
1800
1833
|
base_item.verbose,
|
|
1801
1834
|
(base_item.argfile_index, base_item.argfile),
|
|
1802
1835
|
processes=base_item.processes,
|
|
1803
|
-
timeout=base_item.timeout
|
|
1836
|
+
timeout=base_item.timeout,
|
|
1804
1837
|
)
|
|
1805
1838
|
yield chunked_item
|
|
1806
1839
|
|
|
@@ -1880,7 +1913,7 @@ def _get_dynamically_created_execution_items(
|
|
|
1880
1913
|
("", None),
|
|
1881
1914
|
pabot_args.get("hive"),
|
|
1882
1915
|
pabot_args["processes"],
|
|
1883
|
-
pabot_args["processtimeout"]
|
|
1916
|
+
pabot_args["processtimeout"],
|
|
1884
1917
|
)
|
|
1885
1918
|
for suite in suite_group
|
|
1886
1919
|
]
|
|
@@ -1982,7 +2015,7 @@ def _group_suites(outs_dir, datasources, options, pabot_args):
|
|
|
1982
2015
|
grouped_suites = (
|
|
1983
2016
|
_chunked_suite_names(shard_suites, pabot_args["processes"])
|
|
1984
2017
|
if pabot_args["chunk"]
|
|
1985
|
-
else _group_by_wait(_group_by_groups(
|
|
2018
|
+
else _group_by_wait(_group_by_groups(shard_suites))
|
|
1986
2019
|
)
|
|
1987
2020
|
grouped_by_depend = _all_grouped_suites_by_depend(grouped_suites)
|
|
1988
2021
|
return grouped_by_depend
|
|
@@ -2019,17 +2052,23 @@ def _verify_depends(suite_names):
|
|
|
2019
2052
|
)
|
|
2020
2053
|
)
|
|
2021
2054
|
if suites_with_depends != suites_with_found_dependencies:
|
|
2022
|
-
raise
|
|
2055
|
+
raise DataError(
|
|
2056
|
+
"Invalid test configuration: Some test suites have dependencies (#DEPENDS) that cannot be found."
|
|
2057
|
+
)
|
|
2023
2058
|
suites_with_circular_dependencies = list(
|
|
2024
2059
|
filter(lambda suite: suite.depends == suite.name, suites_with_depends)
|
|
2025
2060
|
)
|
|
2026
2061
|
if suites_with_circular_dependencies:
|
|
2027
|
-
raise
|
|
2062
|
+
raise DataError(
|
|
2063
|
+
"Invalid test configuration: Test suites cannot depend on themselves."
|
|
2064
|
+
)
|
|
2028
2065
|
grouped_suites = list(
|
|
2029
2066
|
filter(lambda suite: isinstance(suite, GroupItem), suite_names)
|
|
2030
2067
|
)
|
|
2031
2068
|
if grouped_suites and suites_with_depends:
|
|
2032
|
-
raise
|
|
2069
|
+
raise DataError(
|
|
2070
|
+
"Invalid test configuration: Cannot use both #DEPENDS and grouped suites."
|
|
2071
|
+
)
|
|
2033
2072
|
|
|
2034
2073
|
|
|
2035
2074
|
def _group_by_depend(suite_names):
|
|
@@ -2057,7 +2096,9 @@ def _group_by_depend(suite_names):
|
|
|
2057
2096
|
dependency_tree += [dependent_on_last_stage]
|
|
2058
2097
|
flattened_dependency_tree = sum(dependency_tree, [])
|
|
2059
2098
|
if len(flattened_dependency_tree) != len(runnable_suites):
|
|
2060
|
-
raise
|
|
2099
|
+
raise DataError(
|
|
2100
|
+
"Invalid test configuration: Circular or unmet dependencies detected between test suites. Please check your #DEPENDS definitions."
|
|
2101
|
+
)
|
|
2061
2102
|
return dependency_tree
|
|
2062
2103
|
|
|
2063
2104
|
|
pabot/pabotlib.py
CHANGED
|
@@ -43,7 +43,6 @@ PABOT_MIN_QUEUE_INDEX_EXECUTING_PARALLEL_VALUE = "pabot_min_queue_index_executin
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class _PabotLib(object):
|
|
46
|
-
|
|
47
46
|
_TAGS_KEY = "tags"
|
|
48
47
|
|
|
49
48
|
def __init__(self, resourcefile=None): # type: (Optional[str]) -> None
|
|
@@ -155,17 +154,19 @@ class _PabotLib(object):
|
|
|
155
154
|
content[self._TAGS_KEY] = []
|
|
156
155
|
self._values[name] = content
|
|
157
156
|
|
|
158
|
-
def import_shared_library(
|
|
157
|
+
def import_shared_library(
|
|
158
|
+
self, name, args=None
|
|
159
|
+
): # type: (str, Iterable[Any]|None) -> int
|
|
159
160
|
if name in self._remote_libraries:
|
|
160
161
|
return self._remote_libraries[name][0]
|
|
161
162
|
if name in STDLIBS:
|
|
162
|
-
import_name =
|
|
163
|
+
import_name = "robot.libraries." + name
|
|
163
164
|
else:
|
|
164
165
|
import_name = name
|
|
165
|
-
imported = Importer(
|
|
166
|
-
|
|
167
|
-
imported, port=0, serve=False, allow_stop=True
|
|
166
|
+
imported = Importer("library").import_class_or_module(
|
|
167
|
+
name_or_path=import_name, instantiate_with_args=args
|
|
168
168
|
)
|
|
169
|
+
server = RobotRemoteServer(imported, port=0, serve=False, allow_stop=True)
|
|
169
170
|
server_thread = threading.Thread(target=server.serve)
|
|
170
171
|
server_thread.start()
|
|
171
172
|
time.sleep(1)
|
|
@@ -197,7 +198,6 @@ class _PabotLib(object):
|
|
|
197
198
|
|
|
198
199
|
|
|
199
200
|
class PabotLib(_PabotLib):
|
|
200
|
-
|
|
201
201
|
__version__ = 0.67
|
|
202
202
|
ROBOT_LIBRARY_SCOPE = "GLOBAL"
|
|
203
203
|
ROBOT_LISTENER_API_VERSION = 2
|
pabot/py3/messages.py
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
pabot/SharedLibrary.py,sha256=mIipGs3ZhKYEakKprcbrMI4P_Un6qI8gE7086xpHaLY,2552
|
|
2
|
+
pabot/__init__.py,sha256=jjZbGiQ4mD-1PiHSWFPP1tnabmVkoFjUPxOGCQdECEc,94
|
|
3
|
+
pabot/arguments.py,sha256=PQuJiRYwkfhzbQLat4rOflfAvDONuBAWhu1SOmVV858,7149
|
|
4
|
+
pabot/clientwrapper.py,sha256=yz7battGs0exysnDeLDWJuzpb2Q-qSjitwxZMO2TlJw,231
|
|
5
|
+
pabot/coordinatorwrapper.py,sha256=nQQ7IowD6c246y8y9nsx0HZbt8vS2XODhPVDjm-lyi0,195
|
|
6
|
+
pabot/execution_items.py,sha256=ktPoGx0yXK6Q_4A8CYW3OFCnCyZQnJb8cPYZULmwyAU,8320
|
|
7
|
+
pabot/pabot.py,sha256=gillkewfdWLPksABZ3ooJPJAmGLSRq0o2SCIxfEiI08,68692
|
|
8
|
+
pabot/pabotlib.py,sha256=FRZKaKy1ybyRkE-0SpaCsUWzxZAzNNU5dAywSm1QoPk,22324
|
|
9
|
+
pabot/result_merger.py,sha256=0LJN5AhgbaXW0OSCvygYvhxY3eOwYp5GntTjLASqsu8,8864
|
|
10
|
+
pabot/robotremoteserver.py,sha256=L3O2QRKSGSE4ux5M1ip5XJMaelqaxQWJxd9wLLdtpzM,22272
|
|
11
|
+
pabot/workerwrapper.py,sha256=BdELUVDs5BmEkdNBcYTlnP22Cj0tUpZEunYQMAKyKWU,185
|
|
12
|
+
pabot/py3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
pabot/py3/client.py,sha256=Od9L4vZ0sozMHq_W_ITQHBBt8kAej40DG58wnxmbHGM,1434
|
|
14
|
+
pabot/py3/coordinator.py,sha256=kBshCzA_1QX_f0WNk42QBJyDYSwSlNM-UEBxOReOj6E,2313
|
|
15
|
+
pabot/py3/messages.py,sha256=7mFr4_0x1JHm5sW8TvKq28Xs_JoeIGku2bX7AyO0kng,2557
|
|
16
|
+
pabot/py3/worker.py,sha256=5rfp4ZiW6gf8GRz6eC0-KUkfx847A91lVtRYpLAv2sg,1612
|
|
17
|
+
robotframework_pabot-4.0.4.dist-info/LICENSE.txt,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
18
|
+
robotframework_pabot-4.0.4.dist-info/METADATA,sha256=0jHKXbl9oKLtKhHi0bOoTWvMfrrIa_eXK6ggemb8xfc,997
|
|
19
|
+
robotframework_pabot-4.0.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
20
|
+
robotframework_pabot-4.0.4.dist-info/entry_points.txt,sha256=JpAIFADTeFOQWdwmn56KpAil8V3-41ZC5ICXCYm3Ng0,43
|
|
21
|
+
robotframework_pabot-4.0.4.dist-info/top_level.txt,sha256=t3OwfEAsSxyxrhjy_GCJYHKbV_X6AIsgeLhYeHvObG4,6
|
|
22
|
+
robotframework_pabot-4.0.4.dist-info/RECORD,,
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
pabot/SharedLibrary.py,sha256=lVYRIajUlMzlNT7bSylLYL248Rumh4dlg4OMl3M988E,2479
|
|
2
|
-
pabot/__init__.py,sha256=_HHnPnSAmYJ5aUmJ4KE2UnHPIlR7HCvMgiN8SrX8afU,93
|
|
3
|
-
pabot/arguments.py,sha256=K9OXolHBrVjE_qhg2KRmC5u8zsUjKO7aICax-SWSmH0,7350
|
|
4
|
-
pabot/clientwrapper.py,sha256=yz7battGs0exysnDeLDWJuzpb2Q-qSjitwxZMO2TlJw,231
|
|
5
|
-
pabot/coordinatorwrapper.py,sha256=nQQ7IowD6c246y8y9nsx0HZbt8vS2XODhPVDjm-lyi0,195
|
|
6
|
-
pabot/execution_items.py,sha256=e7mjwAdgd-qGHjk9fR5QmIxqf6_c73rVbMGHVfU924I,8327
|
|
7
|
-
pabot/pabot.py,sha256=eYL3LLpy2GXeKiqnRvaal9yvZYqXVEK9jV-zZQi1o2E,67663
|
|
8
|
-
pabot/pabotlib.py,sha256=XgiEtDJ8ZkoOcBAWokgzY5TlfYIL4hZN9Q3-Kj-5HhQ,22312
|
|
9
|
-
pabot/result_merger.py,sha256=0LJN5AhgbaXW0OSCvygYvhxY3eOwYp5GntTjLASqsu8,8864
|
|
10
|
-
pabot/robotremoteserver.py,sha256=L3O2QRKSGSE4ux5M1ip5XJMaelqaxQWJxd9wLLdtpzM,22272
|
|
11
|
-
pabot/workerwrapper.py,sha256=BdELUVDs5BmEkdNBcYTlnP22Cj0tUpZEunYQMAKyKWU,185
|
|
12
|
-
pabot/py3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
pabot/py3/client.py,sha256=Od9L4vZ0sozMHq_W_ITQHBBt8kAej40DG58wnxmbHGM,1434
|
|
14
|
-
pabot/py3/coordinator.py,sha256=kBshCzA_1QX_f0WNk42QBJyDYSwSlNM-UEBxOReOj6E,2313
|
|
15
|
-
pabot/py3/messages.py,sha256=7earx6jFDSaK7LofHHv1fWuPEw7uxYN48JT6NZMWEdk,2558
|
|
16
|
-
pabot/py3/worker.py,sha256=5rfp4ZiW6gf8GRz6eC0-KUkfx847A91lVtRYpLAv2sg,1612
|
|
17
|
-
robotframework_pabot-3.1.0.dist-info/LICENSE.txt,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
18
|
-
robotframework_pabot-3.1.0.dist-info/METADATA,sha256=qClRqQ5x5M1IZtAZoFVlOC_jGBTdonBKUDZUJY5dwgE,997
|
|
19
|
-
robotframework_pabot-3.1.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
20
|
-
robotframework_pabot-3.1.0.dist-info/entry_points.txt,sha256=JpAIFADTeFOQWdwmn56KpAil8V3-41ZC5ICXCYm3Ng0,43
|
|
21
|
-
robotframework_pabot-3.1.0.dist-info/top_level.txt,sha256=t3OwfEAsSxyxrhjy_GCJYHKbV_X6AIsgeLhYeHvObG4,6
|
|
22
|
-
robotframework_pabot-3.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{robotframework_pabot-3.1.0.dist-info → robotframework_pabot-4.0.4.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|