potassco-benchmark-tool 2.1.1__py3-none-any.whl → 2.2.0__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.
- benchmarktool/entry_points.py +71 -33
- benchmarktool/init/runscripts/runscript-all.xml +2 -2
- benchmarktool/init/runscripts/runscript-dist.xml +2 -2
- benchmarktool/init/runscripts/runscript-example.xml +1 -1
- benchmarktool/init/templates/seq-generic.sh +20 -5
- benchmarktool/result/ipynb_gen.py +2 -0
- benchmarktool/result/result.py +26 -16
- benchmarktool/result/xlsx_gen.py +935 -0
- benchmarktool/resultparser/clasp.py +20 -9
- benchmarktool/runscript/parser.py +235 -134
- benchmarktool/runscript/runscript.py +190 -191
- benchmarktool/tools.py +22 -2
- {potassco_benchmark_tool-2.1.1.dist-info → potassco_benchmark_tool-2.2.0.dist-info}/METADATA +24 -11
- potassco_benchmark_tool-2.2.0.dist-info/RECORD +26 -0
- benchmarktool/init/templates/seq-generic-single.sh +0 -27
- benchmarktool/init/templates/seq-generic-zip.sh +0 -14
- benchmarktool/result/ods_config.py +0 -42
- benchmarktool/result/ods_gen.py +0 -714
- potassco_benchmark_tool-2.1.1.dist-info/RECORD +0 -29
- {potassco_benchmark_tool-2.1.1.dist-info → potassco_benchmark_tool-2.2.0.dist-info}/WHEEL +0 -0
- {potassco_benchmark_tool-2.1.1.dist-info → potassco_benchmark_tool-2.2.0.dist-info}/entry_points.txt +0 -0
- {potassco_benchmark_tool-2.1.1.dist-info → potassco_benchmark_tool-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {potassco_benchmark_tool-2.1.1.dist-info → potassco_benchmark_tool-2.2.0.dist-info}/top_level.txt +0 -0
|
@@ -32,25 +32,32 @@ PAR = 2
|
|
|
32
32
|
|
|
33
33
|
# pylint: disable=unused-argument
|
|
34
34
|
def parse(
|
|
35
|
-
|
|
35
|
+
path: str, runspec: "runscript.Runspec", instance: "runscript.Benchmark.Instance", run: int
|
|
36
36
|
) -> dict[str, tuple[str, Any]]:
|
|
37
37
|
"""
|
|
38
38
|
Extracts some clasp statistics.
|
|
39
39
|
|
|
40
40
|
Attributes:
|
|
41
|
-
|
|
41
|
+
path (str): The path to the run directory.
|
|
42
42
|
runspec (Runspec): The run specification of the benchmark.
|
|
43
43
|
instance (Benchmark.Instance): The benchmark instance.
|
|
44
|
+
run (int): The run number.
|
|
44
45
|
"""
|
|
45
46
|
timeout = runspec.project.job.timeout
|
|
46
47
|
res: dict[str, tuple[str, Any]] = {"time": ("float", timeout)}
|
|
47
48
|
for f in ["runsolver.solver", "runsolver.watcher"]:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
for
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
try:
|
|
50
|
+
with open(os.path.join(path, f), errors="ignore", encoding="utf-8") as file:
|
|
51
|
+
for line in file:
|
|
52
|
+
for val, reg in clasp_re.items():
|
|
53
|
+
m = reg[1].match(line)
|
|
54
|
+
if m:
|
|
55
|
+
res[val] = (reg[0], float(m.group("val")) if reg[0] == "float" else m.group("val"))
|
|
56
|
+
except FileNotFoundError:
|
|
57
|
+
sys.stderr.write(
|
|
58
|
+
f"*** WARNING: Result file '{f}' not found for run {run} of instance '{instance.name}' "
|
|
59
|
+
f"for system '{runspec.system.name}-{runspec.system.version}'! ({path})\n"
|
|
60
|
+
)
|
|
54
61
|
|
|
55
62
|
if "rstatus" in res and res["rstatus"][1] == "out of memory":
|
|
56
63
|
res["error"] = ("string", "std::bad_alloc")
|
|
@@ -70,7 +77,11 @@ def parse(
|
|
|
70
77
|
if timedout:
|
|
71
78
|
res["time"] = ("float", timeout)
|
|
72
79
|
if error:
|
|
73
|
-
sys.stderr.write(
|
|
80
|
+
sys.stderr.write(
|
|
81
|
+
f"*** WARNING: Run {run} of instance '{instance.name}' "
|
|
82
|
+
f"for system '{runspec.system.name}-{runspec.system.version}' "
|
|
83
|
+
f"failed with unrecognized status or error! ({path})\n"
|
|
84
|
+
)
|
|
74
85
|
result["error"] = ("float", int(error))
|
|
75
86
|
result["timeout"] = ("float", int(timedout))
|
|
76
87
|
result["memout"] = ("float", int(memout))
|
|
@@ -6,6 +6,7 @@ representation in form of python classes.
|
|
|
6
6
|
|
|
7
7
|
__author__ = "Roland Kaminski"
|
|
8
8
|
import os
|
|
9
|
+
import sys
|
|
9
10
|
from typing import Any
|
|
10
11
|
|
|
11
12
|
from lxml import etree # type: ignore[import-untyped]
|
|
@@ -112,13 +113,14 @@ class Parser:
|
|
|
112
113
|
</xs:sequence>
|
|
113
114
|
<xs:attribute name="name" type="nameType" use="required"/>
|
|
114
115
|
<xs:attribute name="cmdline" type="xs:string"/>
|
|
116
|
+
<xs:attribute name="cmdline_post" type="xs:string"/>
|
|
115
117
|
<xs:attribute name="tag">
|
|
116
118
|
<xs:simpleType>
|
|
117
119
|
<xs:list itemType="nameType"/>
|
|
118
120
|
</xs:simpleType>
|
|
119
121
|
</xs:attribute>
|
|
120
|
-
<xs:attribute name="
|
|
121
|
-
<xs:attribute name="
|
|
122
|
+
<xs:attribute name="dist_template" type="xs:string"/>
|
|
123
|
+
<xs:attribute name="dist_options" type="xs:string"/>
|
|
122
124
|
<xs:anyAttribute processContents="lax"/>
|
|
123
125
|
</xs:complexType>
|
|
124
126
|
</xs:element>
|
|
@@ -128,6 +130,7 @@ class Parser:
|
|
|
128
130
|
<xs:attribute name="measures" type="nameType" use="required"/>
|
|
129
131
|
<xs:attribute name="config" type="nameType" use="required"/>
|
|
130
132
|
<xs:attribute name="cmdline" type="xs:string"/>
|
|
133
|
+
<xs:attribute name="cmdline_post" type="xs:string"/>
|
|
131
134
|
</xs:complexType>
|
|
132
135
|
|
|
133
136
|
<!-- generic attributes for jobs-->
|
|
@@ -136,6 +139,7 @@ class Parser:
|
|
|
136
139
|
<xs:attribute name="timeout" type="timeType" use="required"/>
|
|
137
140
|
<xs:attribute name="runs" type="xs:positiveInteger" use="required"/>
|
|
138
141
|
<xs:attribute name="memout" type="xs:positiveInteger"/>
|
|
142
|
+
<xs:attribute name="template_options" type="xs:string"/>
|
|
139
143
|
<xs:anyAttribute processContents="lax"/>
|
|
140
144
|
</xs:attributeGroup>
|
|
141
145
|
|
|
@@ -326,145 +330,188 @@ class Parser:
|
|
|
326
330
|
)
|
|
327
331
|
schema = etree.XMLSchema(schemadoc)
|
|
328
332
|
|
|
329
|
-
|
|
330
|
-
doc = etree.parse(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
333
|
+
try:
|
|
334
|
+
doc = etree.parse(file_name)
|
|
335
|
+
except (etree.XMLSyntaxError, OSError) as e:
|
|
336
|
+
if isinstance(e, OSError):
|
|
337
|
+
sys.stderr.write(f"*** ERROR: Runscript file '{file_name}' not found.\n")
|
|
338
|
+
sys.exit(1)
|
|
339
|
+
sys.stderr.write(f"*** ERROR: XML Syntax Error in runscript: {e}\n")
|
|
340
|
+
sys.exit(1)
|
|
335
341
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
try:
|
|
343
|
+
schema.assertValid(doc)
|
|
344
|
+
except etree.DocumentInvalid as e:
|
|
345
|
+
sys.stderr.write(f"*** ERROR: Invalid runscript file: {e}\n")
|
|
346
|
+
sys.exit(1)
|
|
347
|
+
|
|
348
|
+
root = doc.getroot()
|
|
349
|
+
run = Runscript(root.get("output"))
|
|
350
|
+
|
|
351
|
+
for node in root.xpath("./distjob"):
|
|
352
|
+
run.add_job(self._parse_job(node, "distjob"))
|
|
353
|
+
|
|
354
|
+
for node in root.xpath("./seqjob"):
|
|
355
|
+
run.add_job(self._parse_job(node, "seqjob"))
|
|
356
|
+
|
|
357
|
+
for node in root.xpath("./machine"):
|
|
358
|
+
machine = Machine(node.get("name"), node.get("cpu"), node.get("memory"))
|
|
359
|
+
run.add_machine(machine)
|
|
360
|
+
|
|
361
|
+
for node in root.xpath("./config"):
|
|
362
|
+
config = Config(node.get("name"), node.get("template"))
|
|
363
|
+
run.add_config(config)
|
|
364
|
+
|
|
365
|
+
compound_settings: dict[str, list[str]] = {}
|
|
366
|
+
system_order = 0
|
|
367
|
+
for node in root.xpath("./system"):
|
|
368
|
+
config = run.configs[node.get("config")]
|
|
369
|
+
system = System(node.get("name"), node.get("version"), node.get("measures"), system_order, config)
|
|
370
|
+
setting_order = 0
|
|
371
|
+
sys_cmdline = node.get("cmdline")
|
|
372
|
+
sys_cmdline_post = node.get("cmdline_post")
|
|
373
|
+
for child in node.xpath("setting"):
|
|
339
374
|
attr = self._filter_attr(
|
|
340
|
-
|
|
375
|
+
child, ["name", "cmdline", "cmdline_post", "tag", "dist_options", "dist_template"]
|
|
341
376
|
)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
377
|
+
compound_settings[child.get("name")] = []
|
|
378
|
+
dist_template = child.get("dist_template")
|
|
379
|
+
if dist_template is None:
|
|
380
|
+
dist_template = "templates/single.dist"
|
|
381
|
+
if child.get("tag") is None:
|
|
382
|
+
tag = set()
|
|
383
|
+
else:
|
|
384
|
+
tag = set(child.get("tag").split(None))
|
|
385
|
+
dist_options = child.get("dist_options")
|
|
386
|
+
if dist_options is None:
|
|
387
|
+
dist_options = ""
|
|
388
|
+
encodings: dict[str, set[str]] = {"_default_": set()}
|
|
389
|
+
for grandchild in child.xpath("./encoding"):
|
|
390
|
+
if grandchild.get("enctag") is None:
|
|
391
|
+
encodings["_default_"].add(os.path.normpath(grandchild.get("file")))
|
|
392
|
+
else:
|
|
393
|
+
enctags = set(grandchild.get("enctag").split(None))
|
|
394
|
+
for t in enctags:
|
|
395
|
+
if t not in encodings:
|
|
396
|
+
encodings[t] = set()
|
|
397
|
+
encodings[t].add(os.path.normpath(grandchild.get("file")))
|
|
398
|
+
|
|
399
|
+
cmdline = " ".join(
|
|
400
|
+
filter(None, [sys_cmdline, child.get("cmdline"), sys_cmdline_post, child.get("cmdline_post")])
|
|
355
401
|
)
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
402
|
+
name = child.get("name")
|
|
403
|
+
compound_settings[child.get("name")].append(name)
|
|
404
|
+
keys = list(attr.keys())
|
|
405
|
+
if keys:
|
|
406
|
+
sys.stderr.write(
|
|
407
|
+
f"""*** INFO: Attribute{'s' if len(keys) > 1 else ''} {', '.join(f"'{k}'" for k in keys)} in setting '{name}' {'are' if len(keys) > 1 else 'is'} currently unused.\n"""
|
|
408
|
+
)
|
|
409
|
+
setting = Setting(
|
|
410
|
+
name=name,
|
|
411
|
+
cmdline=cmdline,
|
|
412
|
+
tag=tag,
|
|
413
|
+
order=setting_order,
|
|
414
|
+
dist_template=dist_template,
|
|
415
|
+
attr=attr,
|
|
416
|
+
dist_options=dist_options,
|
|
417
|
+
encodings=encodings,
|
|
366
418
|
)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
for
|
|
420
|
-
benchmark
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
group = child.get("group").lower() == "true"
|
|
424
|
-
else:
|
|
425
|
-
group = False
|
|
426
|
-
element = Benchmark.Folder(child.get("path"), group)
|
|
427
|
-
if child.get("enctag") is None:
|
|
428
|
-
tag = set()
|
|
429
|
-
else:
|
|
430
|
-
tag = set(child.get("enctag").split(None))
|
|
431
|
-
element.add_enctags(tag)
|
|
432
|
-
for grandchild in child.xpath("./encoding"):
|
|
433
|
-
element.add_encoding(grandchild.get("file"))
|
|
434
|
-
for grandchild in child.xpath("./ignore"):
|
|
435
|
-
element.add_ignore(grandchild.get("prefix"))
|
|
436
|
-
benchmark.add_element(element)
|
|
437
|
-
for child in node.xpath("./files"):
|
|
438
|
-
element = Benchmark.Files(child.get("path"))
|
|
439
|
-
if child.get("enctag") is None:
|
|
440
|
-
tag = set()
|
|
441
|
-
else:
|
|
442
|
-
tag = set(child.get("enctag").split(None))
|
|
443
|
-
element.add_enctags(tag)
|
|
444
|
-
for grandchild in child.xpath("./encoding"):
|
|
445
|
-
element.add_encoding(grandchild.get("file"))
|
|
446
|
-
for grandchild in child.xpath("./add"):
|
|
447
|
-
element.add_file(grandchild.get("file"), grandchild.get("group"))
|
|
448
|
-
benchmark.add_element(element)
|
|
449
|
-
run.add_benchmark(benchmark)
|
|
450
|
-
|
|
451
|
-
for node in root.xpath("./project"):
|
|
452
|
-
project = Project(node.get("name"), run, run.jobs[node.get("job")])
|
|
453
|
-
run.add_project(project)
|
|
454
|
-
for child in node.xpath("./runspec"):
|
|
455
|
-
for setting_name in compound_settings[child.get("setting")]:
|
|
456
|
-
project.add_runspec(
|
|
457
|
-
child.get("machine"),
|
|
458
|
-
child.get("system"),
|
|
459
|
-
child.get("version"),
|
|
460
|
-
setting_name,
|
|
461
|
-
child.get("benchmark"),
|
|
462
|
-
)
|
|
463
|
-
|
|
464
|
-
for child in node.xpath("./runtag"):
|
|
465
|
-
project.add_runtag(child.get("machine"), child.get("benchmark"), child.get("tag"))
|
|
419
|
+
system.add_setting(setting)
|
|
420
|
+
setting_order += 1
|
|
421
|
+
|
|
422
|
+
run.systems[(system.name, system.version)] = system
|
|
423
|
+
system_order += 1
|
|
424
|
+
|
|
425
|
+
element: Any
|
|
426
|
+
for node in root.xpath("./benchmark"):
|
|
427
|
+
benchmark = Benchmark(node.get("name"))
|
|
428
|
+
for child in node.xpath("./folder"):
|
|
429
|
+
if child.get("group") is not None:
|
|
430
|
+
group = child.get("group").lower() == "true"
|
|
431
|
+
else:
|
|
432
|
+
group = False
|
|
433
|
+
element = Benchmark.Folder(child.get("path"), group)
|
|
434
|
+
if child.get("enctag") is None:
|
|
435
|
+
tag = set()
|
|
436
|
+
else:
|
|
437
|
+
tag = set(child.get("enctag").split(None))
|
|
438
|
+
element.add_enctags(tag)
|
|
439
|
+
for grandchild in child.xpath("./encoding"):
|
|
440
|
+
element.add_encoding(grandchild.get("file"))
|
|
441
|
+
for grandchild in child.xpath("./ignore"):
|
|
442
|
+
element.add_ignore(grandchild.get("prefix"))
|
|
443
|
+
benchmark.add_element(element)
|
|
444
|
+
for child in node.xpath("./files"):
|
|
445
|
+
element = Benchmark.Files(child.get("path"))
|
|
446
|
+
if child.get("enctag") is None:
|
|
447
|
+
tag = set()
|
|
448
|
+
else:
|
|
449
|
+
tag = set(child.get("enctag").split(None))
|
|
450
|
+
element.add_enctags(tag)
|
|
451
|
+
for grandchild in child.xpath("./encoding"):
|
|
452
|
+
element.add_encoding(grandchild.get("file"))
|
|
453
|
+
for grandchild in child.xpath("./add"):
|
|
454
|
+
element.add_file(grandchild.get("file"), grandchild.get("group"))
|
|
455
|
+
benchmark.add_element(element)
|
|
456
|
+
run.add_benchmark(benchmark)
|
|
457
|
+
|
|
458
|
+
for node in root.xpath("./project"):
|
|
459
|
+
project = Project(node.get("name"), run, run.jobs[node.get("job")])
|
|
460
|
+
run.add_project(project)
|
|
461
|
+
for child in node.xpath("./runspec"):
|
|
462
|
+
for setting_name in compound_settings[child.get("setting")]:
|
|
463
|
+
project.add_runspec(
|
|
464
|
+
machine_name=child.get("machine"),
|
|
465
|
+
system_name=child.get("system"),
|
|
466
|
+
system_version=child.get("version"),
|
|
467
|
+
setting_name=setting_name,
|
|
468
|
+
benchmark_name=child.get("benchmark"),
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
for child in node.xpath("./runtag"):
|
|
472
|
+
project.add_runtag(child.get("machine"), child.get("benchmark"), child.get("tag"))
|
|
473
|
+
|
|
474
|
+
self.validate_components(run)
|
|
466
475
|
return run
|
|
467
476
|
|
|
477
|
+
def validate_components(self, run: Runscript) -> None:
|
|
478
|
+
"""
|
|
479
|
+
Check runscript for the existence of all required components.
|
|
480
|
+
"""
|
|
481
|
+
# machine
|
|
482
|
+
if not run.machines:
|
|
483
|
+
sys.stderr.write("*** WARNING: No machine defined in runscript.\n")
|
|
484
|
+
|
|
485
|
+
# config
|
|
486
|
+
if not run.configs:
|
|
487
|
+
sys.stderr.write("*** WARNING: No config defined in runscript.\n")
|
|
488
|
+
|
|
489
|
+
# system
|
|
490
|
+
if not run.systems:
|
|
491
|
+
sys.stderr.write("*** WARNING: No system defined in runscript.\n")
|
|
492
|
+
|
|
493
|
+
# setting
|
|
494
|
+
for system in run.systems.values():
|
|
495
|
+
if not system.settings:
|
|
496
|
+
sys.stderr.write(f"*** WARNING: No setting defined for system '{system.name}-{system.version}'.\n")
|
|
497
|
+
|
|
498
|
+
# job
|
|
499
|
+
if not run.jobs:
|
|
500
|
+
sys.stderr.write("*** WARNING: No job defined in runscript.\n")
|
|
501
|
+
|
|
502
|
+
# benchmark
|
|
503
|
+
if not run.benchmarks:
|
|
504
|
+
sys.stderr.write("*** WARNING: No benchmark defined in runscript.\n")
|
|
505
|
+
|
|
506
|
+
# instances
|
|
507
|
+
for benchmark in run.benchmarks.values():
|
|
508
|
+
if not benchmark.elements:
|
|
509
|
+
sys.stderr.write(f"*** WARNING: No instance folder/files defined for benchmark '{benchmark.name}'.\n")
|
|
510
|
+
|
|
511
|
+
# project
|
|
512
|
+
if not run.projects:
|
|
513
|
+
sys.stderr.write("*** WARNING: No project defined in runscript.\n")
|
|
514
|
+
|
|
468
515
|
def _filter_attr(self, node: etree._Element, skip: list[str]) -> dict[str, Any]:
|
|
469
516
|
"""
|
|
470
517
|
Returns a dictionary containing all attributes of a given node.
|
|
@@ -475,3 +522,57 @@ class Parser:
|
|
|
475
522
|
if not key in skip:
|
|
476
523
|
attr[key] = val
|
|
477
524
|
return attr
|
|
525
|
+
|
|
526
|
+
def _parse_job(self, node: etree._Element, job_type: str) -> DistJob | SeqJob:
|
|
527
|
+
"""
|
|
528
|
+
Parses a job node and returns the corresponding job instance.
|
|
529
|
+
"""
|
|
530
|
+
attr_filter = ["name", "timeout", "memout", "runs", "template_options"]
|
|
531
|
+
kwargs = {
|
|
532
|
+
"name": node.get("name"),
|
|
533
|
+
"timeout": tools.xml_to_seconds_time(node.get("timeout")),
|
|
534
|
+
"runs": int(node.get("runs")),
|
|
535
|
+
}
|
|
536
|
+
memout = node.get("memout")
|
|
537
|
+
if memout is not None:
|
|
538
|
+
kwargs["memout"] = int(memout)
|
|
539
|
+
template_options = node.get("template_options")
|
|
540
|
+
if template_options is None:
|
|
541
|
+
template_options = ""
|
|
542
|
+
kwargs["template_options"] = template_options
|
|
543
|
+
|
|
544
|
+
if job_type == "distjob":
|
|
545
|
+
attr = self._filter_attr(node, attr_filter + ["script_mode", "walltime", "cpt", "partition"])
|
|
546
|
+
keys = list(attr.keys())
|
|
547
|
+
if keys:
|
|
548
|
+
sys.stderr.write(
|
|
549
|
+
f"""*** INFO: Attribute{'s' if len(keys) > 1 else ''} {', '.join(f"'{k}'" for k in keys)} in distjob '{node.get('name')}' {'are' if len(keys) > 1 else 'is'} currently unused.\n"""
|
|
550
|
+
)
|
|
551
|
+
kwargs.update(
|
|
552
|
+
{
|
|
553
|
+
"attr": attr,
|
|
554
|
+
"script_mode": node.get("script_mode"),
|
|
555
|
+
"walltime": tools.xml_to_seconds_time(node.get("walltime")),
|
|
556
|
+
"cpt": int(node.get("cpt")),
|
|
557
|
+
}
|
|
558
|
+
)
|
|
559
|
+
partition = node.get("partition")
|
|
560
|
+
if partition is not None:
|
|
561
|
+
kwargs["partition"] = partition
|
|
562
|
+
return DistJob(**kwargs) # pylint: disable=missing-kwoa
|
|
563
|
+
if job_type == "seqjob":
|
|
564
|
+
attr = self._filter_attr(node, attr_filter + ["parallel"])
|
|
565
|
+
keys = list(attr.keys())
|
|
566
|
+
if keys:
|
|
567
|
+
sys.stderr.write(
|
|
568
|
+
f"""*** INFO: Attribute{'s' if len(keys) > 1 else ''} {', '.join(f"'{k}'" for k in keys)} in seqjob '{node.get('name')}' {'are' if len(keys) > 1 else 'is'} currently unused.\n"""
|
|
569
|
+
)
|
|
570
|
+
kwargs.update(
|
|
571
|
+
{
|
|
572
|
+
"attr": attr,
|
|
573
|
+
"parallel": int(node.get("parallel")),
|
|
574
|
+
}
|
|
575
|
+
)
|
|
576
|
+
return SeqJob(**kwargs) # pylint: disable=missing-kwoa
|
|
577
|
+
# Should never happen, checked by xml schema
|
|
578
|
+
raise ValueError(f"Unknown job type: {job_type}") # nocoverage
|