robotframework-pabot 2.14.0__tar.gz → 2.16.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-pabot-2.14.0 → robotframework-pabot-2.16.0}/PKG-INFO +1 -1
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/README.md +4 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/__init__.py +1 -1
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/arguments.py +6 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/pabot.py +33 -7
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/result_merger.py +1 -1
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/PKG-INFO +1 -1
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/LICENSE.txt +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/MANIFEST.in +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/pyproject.toml +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/setup.cfg +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/setup.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/SharedLibrary.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/clientwrapper.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/coordinatorwrapper.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/execution_items.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/pabotlib.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/py3/__init__.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/py3/client.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/py3/coordinator.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/py3/messages.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/py3/worker.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/robotremoteserver.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/pabot/workerwrapper.py +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/SOURCES.txt +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/dependency_links.txt +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/entry_points.txt +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/requires.txt +0 -0
- {robotframework-pabot-2.14.0 → robotframework-pabot-2.16.0}/src/robotframework_pabot.egg-info/top_level.txt +0 -0
|
@@ -57,6 +57,7 @@ There are several ways you can help in improving this tool:
|
|
|
57
57
|
|
|
58
58
|
pabot [--verbose|--testlevelsplit|--command .. --end-command|
|
|
59
59
|
--processes num|--pabotlib|--pabotlibhost host|--pabotlibport port|
|
|
60
|
+
--processtimeout num|
|
|
60
61
|
--shard i/n|
|
|
61
62
|
--artifacts extensions|--artifactsinsubfolders|
|
|
62
63
|
--resourcefile file|--argumentfile[num] file|--suitesfrom file]
|
|
@@ -100,6 +101,9 @@ Supports all [Robot Framework command line options](https://robotframework.org/r
|
|
|
100
101
|
Port number of the PabotLib remote server (default is 8270)
|
|
101
102
|
See --pabotlibhost for more information
|
|
102
103
|
|
|
104
|
+
--processtimeout [TIMEOUT]
|
|
105
|
+
Maximum time in seconds to wait for a process before killing it. If not set, there's no timeout.
|
|
106
|
+
|
|
103
107
|
--resourcefile [FILEPATH]
|
|
104
108
|
Indicator for a file that can contain shared variables for distributing resources. This needs to be used together with pabotlib option. Resource file syntax is same as Windows ini files. Where a section is a shared set of variables.
|
|
105
109
|
|
|
@@ -72,6 +72,7 @@ def _parse_pabot_args(args): # type: (List[str]) -> Tuple[List[str], Dict[str,
|
|
|
72
72
|
"pabotlibhost": "127.0.0.1",
|
|
73
73
|
"pabotlibport": 8270,
|
|
74
74
|
"processes": _processes_count(),
|
|
75
|
+
"processtimeout": None,
|
|
75
76
|
"artifacts": ["png"],
|
|
76
77
|
"artifactsinsubfolders": False,
|
|
77
78
|
"shardindex": 0,
|
|
@@ -93,6 +94,7 @@ def _parse_pabot_args(args): # type: (List[str]) -> Tuple[List[str], Dict[str,
|
|
|
93
94
|
"pabotlib",
|
|
94
95
|
"pabotlibhost",
|
|
95
96
|
"pabotlibport",
|
|
97
|
+
"processtimeout",
|
|
96
98
|
"ordering",
|
|
97
99
|
"suitesfrom",
|
|
98
100
|
"artifacts",
|
|
@@ -149,6 +151,10 @@ def _parse_pabot_args(args): # type: (List[str]) -> Tuple[List[str], Dict[str,
|
|
|
149
151
|
pabot_args["pabotlibport"] = int(args[1])
|
|
150
152
|
args = args[2:]
|
|
151
153
|
continue
|
|
154
|
+
if args[0] == "--processtimeout":
|
|
155
|
+
pabot_args["processtimeout"] = int(args[1])
|
|
156
|
+
args = args[2:]
|
|
157
|
+
continue
|
|
152
158
|
if args[0] == "--suitesfrom":
|
|
153
159
|
pabot_args["suitesfrom"] = args[1]
|
|
154
160
|
args = args[2:]
|
|
@@ -54,6 +54,9 @@ options (these must be before normal RF options):
|
|
|
54
54
|
--pabotlibport [PORT]
|
|
55
55
|
Port number of the PabotLib remote server (default is 8270)
|
|
56
56
|
|
|
57
|
+
--processtimeout [TIMEOUT]
|
|
58
|
+
Maximum time in seconds to wait for a process before killing it. If not set, there's no timeout.
|
|
59
|
+
|
|
57
60
|
--ordering [FILE PATH]
|
|
58
61
|
Optionally give execution order from a file.
|
|
59
62
|
|
|
@@ -229,6 +232,7 @@ def execute_and_wait_with(item):
|
|
|
229
232
|
caller_id,
|
|
230
233
|
item.index,
|
|
231
234
|
item.execution_item.type != "test",
|
|
235
|
+
process_timeout=item.timeout
|
|
232
236
|
)
|
|
233
237
|
outputxml_preprocessing(
|
|
234
238
|
item.options, outs_dir, name, item.verbose, _make_id(), caller_id
|
|
@@ -286,8 +290,9 @@ def _try_execute_and_wait(
|
|
|
286
290
|
caller_id,
|
|
287
291
|
my_index=-1,
|
|
288
292
|
show_stdout_on_failure=False,
|
|
293
|
+
process_timeout=None
|
|
289
294
|
):
|
|
290
|
-
# type: (List[str], str, str, bool, int, str, int, bool) -> None
|
|
295
|
+
# type: (List[str], str, str, bool, int, str, int, bool, Optional[int]) -> None
|
|
291
296
|
plib = None
|
|
292
297
|
is_ignored = False
|
|
293
298
|
if _pabotlib_in_use():
|
|
@@ -296,7 +301,7 @@ def _try_execute_and_wait(
|
|
|
296
301
|
with open(os.path.join(outs_dir, cmd[0] + "_stdout.out"), "w") as stdout:
|
|
297
302
|
with open(os.path.join(outs_dir, cmd[0] + "_stderr.out"), "w") as stderr:
|
|
298
303
|
process, (rc, elapsed) = _run(
|
|
299
|
-
cmd, stderr, stdout, item_name, verbose, pool_id, my_index, outs_dir
|
|
304
|
+
cmd, stderr, stdout, item_name, verbose, pool_id, my_index, outs_dir, process_timeout
|
|
300
305
|
)
|
|
301
306
|
except:
|
|
302
307
|
_write(traceback.format_exc())
|
|
@@ -469,8 +474,8 @@ def _increase_completed(plib, my_index):
|
|
|
469
474
|
)
|
|
470
475
|
|
|
471
476
|
|
|
472
|
-
def _run(command, stderr, stdout, item_name, verbose, pool_id, item_index, outs_dir):
|
|
473
|
-
# type: (List[str], IO[Any], IO[Any], str, bool, int, int, str) -> Tuple[Union[subprocess.Popen[bytes], subprocess.Popen], Tuple[int, float]]
|
|
477
|
+
def _run(command, stderr, stdout, item_name, verbose, pool_id, item_index, outs_dir, process_timeout):
|
|
478
|
+
# type: (List[str], IO[Any], IO[Any], str, bool, int, int, str, Optional[int]) -> Tuple[Union[subprocess.Popen[bytes], subprocess.Popen], Tuple[int, float]]
|
|
474
479
|
timestamp = datetime.datetime.now()
|
|
475
480
|
cmd = " ".join(command)
|
|
476
481
|
if PY2:
|
|
@@ -498,10 +503,10 @@ def _run(command, stderr, stdout, item_name, verbose, pool_id, item_index, outs_
|
|
|
498
503
|
"EXECUTING %s" % item_name,
|
|
499
504
|
timestamp=timestamp,
|
|
500
505
|
)
|
|
501
|
-
return process, _wait_for_return_code(process, item_name, pool_id, item_index)
|
|
506
|
+
return process, _wait_for_return_code(process, item_name, pool_id, item_index, process_timeout)
|
|
502
507
|
|
|
503
508
|
|
|
504
|
-
def _wait_for_return_code(process, item_name, pool_id, item_index):
|
|
509
|
+
def _wait_for_return_code(process, item_name, pool_id, item_index, process_timeout):
|
|
505
510
|
rc = None
|
|
506
511
|
elapsed = 0
|
|
507
512
|
ping_time = ping_interval = 150
|
|
@@ -509,6 +514,19 @@ def _wait_for_return_code(process, item_name, pool_id, item_index):
|
|
|
509
514
|
rc = process.poll()
|
|
510
515
|
time.sleep(0.1)
|
|
511
516
|
elapsed += 1
|
|
517
|
+
|
|
518
|
+
if process_timeout and elapsed / 10.0 >= process_timeout:
|
|
519
|
+
process.terminate()
|
|
520
|
+
process.wait()
|
|
521
|
+
rc = -1 # Set a return code indicating that the process was killed due to timeout
|
|
522
|
+
_write_with_id(
|
|
523
|
+
process,
|
|
524
|
+
pool_id,
|
|
525
|
+
item_index,
|
|
526
|
+
"Process %s killed due to exceeding the maximum timeout of %s seconds" % (item_name, process_timeout),
|
|
527
|
+
)
|
|
528
|
+
break
|
|
529
|
+
|
|
512
530
|
if elapsed == ping_time:
|
|
513
531
|
ping_interval += 50
|
|
514
532
|
ping_time += ping_interval
|
|
@@ -518,9 +536,11 @@ def _wait_for_return_code(process, item_name, pool_id, item_index):
|
|
|
518
536
|
item_index,
|
|
519
537
|
"still running %s after %s seconds" % (item_name, elapsed / 10.0),
|
|
520
538
|
)
|
|
539
|
+
|
|
521
540
|
return rc, elapsed / 10.0
|
|
522
541
|
|
|
523
542
|
|
|
543
|
+
|
|
524
544
|
def _read_file(file_handle):
|
|
525
545
|
try:
|
|
526
546
|
with open(file_handle.name, "r") as content_file:
|
|
@@ -1238,6 +1258,7 @@ def _options_for_rebot(options, start_time_string, end_time_string):
|
|
|
1238
1258
|
"maxassignlength",
|
|
1239
1259
|
"maxerrorlines",
|
|
1240
1260
|
"monitorcolors",
|
|
1261
|
+
"parser",
|
|
1241
1262
|
"prerunmodifier",
|
|
1242
1263
|
"quiet",
|
|
1243
1264
|
"randomize",
|
|
@@ -1617,8 +1638,9 @@ class QueueItem(object):
|
|
|
1617
1638
|
argfile,
|
|
1618
1639
|
hive=None,
|
|
1619
1640
|
processes=0,
|
|
1641
|
+
timeout=None
|
|
1620
1642
|
):
|
|
1621
|
-
# type: (List[str], str, Dict[str, object], ExecutionItem, List[str], bool, Tuple[str, Optional[str]], Optional[str], int) -> None
|
|
1643
|
+
# type: (List[str], str, Dict[str, object], ExecutionItem, List[str], bool, Tuple[str, Optional[str]], Optional[str], int, Optional[int]) -> None
|
|
1622
1644
|
self.datasources = datasources
|
|
1623
1645
|
self.outs_dir = (
|
|
1624
1646
|
outs_dir.encode("utf-8") if PY2 and is_unicode(outs_dir) else outs_dir
|
|
@@ -1636,6 +1658,7 @@ class QueueItem(object):
|
|
|
1636
1658
|
self.last_level = None
|
|
1637
1659
|
self.hive = hive
|
|
1638
1660
|
self.processes = processes
|
|
1661
|
+
self.timeout = timeout
|
|
1639
1662
|
|
|
1640
1663
|
@property
|
|
1641
1664
|
def index(self):
|
|
@@ -1713,6 +1736,7 @@ def _create_items(datasources, opts_for_run, outs_dir, pabot_args, suite_group):
|
|
|
1713
1736
|
argfile,
|
|
1714
1737
|
pabot_args.get("hive"),
|
|
1715
1738
|
pabot_args["processes"],
|
|
1739
|
+
pabot_args["processtimeout"]
|
|
1716
1740
|
)
|
|
1717
1741
|
for suite in suite_group
|
|
1718
1742
|
for argfile in pabot_args["argumentfiles"] or [("", None)]
|
|
@@ -1757,6 +1781,7 @@ def _chunk_items(items, chunk_size):
|
|
|
1757
1781
|
base_item.verbose,
|
|
1758
1782
|
(base_item.argfile_index, base_item.argfile),
|
|
1759
1783
|
processes=base_item.processes,
|
|
1784
|
+
timeout=base_item.timeout
|
|
1760
1785
|
)
|
|
1761
1786
|
yield chunked_item
|
|
1762
1787
|
|
|
@@ -1836,6 +1861,7 @@ def _get_dynamically_created_execution_items(
|
|
|
1836
1861
|
("", None),
|
|
1837
1862
|
pabot_args.get("hive"),
|
|
1838
1863
|
pabot_args["processes"],
|
|
1864
|
+
pabot_args["processtimeout"]
|
|
1839
1865
|
)
|
|
1840
1866
|
for suite in suite_group
|
|
1841
1867
|
]
|
|
@@ -56,7 +56,7 @@ class ResultMerger(SuiteVisitor):
|
|
|
56
56
|
try:
|
|
57
57
|
self._set_prefix(merged.source)
|
|
58
58
|
merged.suite.visit(self)
|
|
59
|
-
self.root.metadata.
|
|
59
|
+
self.root.metadata.update(merged.suite.metadata)
|
|
60
60
|
if self.errors != merged.errors:
|
|
61
61
|
self.errors.add(merged.errors)
|
|
62
62
|
except:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|