jolt 0.9.76__py3-none-any.whl → 0.9.429__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.
- jolt/__init__.py +88 -7
- jolt/__main__.py +9 -1
- jolt/bin/fstree-darwin-x86_64 +0 -0
- jolt/bin/fstree-linux-x86_64 +0 -0
- jolt/cache.py +839 -367
- jolt/chroot.py +156 -0
- jolt/cli.py +362 -143
- jolt/common_pb2.py +63 -0
- jolt/common_pb2_grpc.py +4 -0
- jolt/config.py +99 -42
- jolt/error.py +19 -4
- jolt/expires.py +2 -2
- jolt/filesystem.py +8 -6
- jolt/graph.py +705 -117
- jolt/hooks.py +63 -1
- jolt/influence.py +129 -6
- jolt/loader.py +369 -121
- jolt/log.py +225 -63
- jolt/manifest.py +28 -38
- jolt/options.py +35 -10
- jolt/pkgs/abseil.py +42 -0
- jolt/pkgs/asio.py +25 -0
- jolt/pkgs/autoconf.py +41 -0
- jolt/pkgs/automake.py +41 -0
- jolt/pkgs/b2.py +31 -0
- jolt/pkgs/boost.py +111 -0
- jolt/pkgs/boringssl.py +32 -0
- jolt/pkgs/busybox.py +39 -0
- jolt/pkgs/bzip2.py +43 -0
- jolt/pkgs/cares.py +29 -0
- jolt/pkgs/catch2.py +36 -0
- jolt/pkgs/cbindgen.py +17 -0
- jolt/pkgs/cista.py +19 -0
- jolt/pkgs/clang.py +44 -0
- jolt/pkgs/cli11.py +23 -0
- jolt/pkgs/cmake.py +48 -0
- jolt/pkgs/cpython.py +196 -0
- jolt/pkgs/crun.py +29 -0
- jolt/pkgs/curl.py +38 -0
- jolt/pkgs/dbus.py +18 -0
- jolt/pkgs/double_conversion.py +24 -0
- jolt/pkgs/fastfloat.py +21 -0
- jolt/pkgs/ffmpeg.py +28 -0
- jolt/pkgs/flatbuffers.py +29 -0
- jolt/pkgs/fmt.py +27 -0
- jolt/pkgs/fstree.py +20 -0
- jolt/pkgs/gflags.py +18 -0
- jolt/pkgs/glib.py +18 -0
- jolt/pkgs/glog.py +25 -0
- jolt/pkgs/glslang.py +21 -0
- jolt/pkgs/golang.py +16 -11
- jolt/pkgs/googlebenchmark.py +18 -0
- jolt/pkgs/googletest.py +46 -0
- jolt/pkgs/gperf.py +15 -0
- jolt/pkgs/grpc.py +73 -0
- jolt/pkgs/hdf5.py +19 -0
- jolt/pkgs/help2man.py +14 -0
- jolt/pkgs/inja.py +28 -0
- jolt/pkgs/jsoncpp.py +31 -0
- jolt/pkgs/libarchive.py +43 -0
- jolt/pkgs/libcap.py +44 -0
- jolt/pkgs/libdrm.py +44 -0
- jolt/pkgs/libedit.py +42 -0
- jolt/pkgs/libevent.py +31 -0
- jolt/pkgs/libexpat.py +27 -0
- jolt/pkgs/libfastjson.py +21 -0
- jolt/pkgs/libffi.py +16 -0
- jolt/pkgs/libglvnd.py +30 -0
- jolt/pkgs/libogg.py +28 -0
- jolt/pkgs/libpciaccess.py +18 -0
- jolt/pkgs/libseccomp.py +21 -0
- jolt/pkgs/libtirpc.py +24 -0
- jolt/pkgs/libtool.py +42 -0
- jolt/pkgs/libunwind.py +35 -0
- jolt/pkgs/libva.py +18 -0
- jolt/pkgs/libvorbis.py +33 -0
- jolt/pkgs/libxml2.py +35 -0
- jolt/pkgs/libxslt.py +17 -0
- jolt/pkgs/libyajl.py +16 -0
- jolt/pkgs/llvm.py +81 -0
- jolt/pkgs/lua.py +54 -0
- jolt/pkgs/lz4.py +26 -0
- jolt/pkgs/m4.py +14 -0
- jolt/pkgs/make.py +17 -0
- jolt/pkgs/mesa.py +81 -0
- jolt/pkgs/meson.py +17 -0
- jolt/pkgs/mstch.py +28 -0
- jolt/pkgs/mysql.py +60 -0
- jolt/pkgs/nasm.py +49 -0
- jolt/pkgs/ncurses.py +30 -0
- jolt/pkgs/ng_log.py +25 -0
- jolt/pkgs/ninja.py +45 -0
- jolt/pkgs/nlohmann_json.py +25 -0
- jolt/pkgs/nodejs.py +19 -11
- jolt/pkgs/opencv.py +24 -0
- jolt/pkgs/openjdk.py +26 -0
- jolt/pkgs/openssl.py +103 -0
- jolt/pkgs/paho.py +76 -0
- jolt/pkgs/patchelf.py +16 -0
- jolt/pkgs/perl.py +42 -0
- jolt/pkgs/pkgconfig.py +64 -0
- jolt/pkgs/poco.py +39 -0
- jolt/pkgs/protobuf.py +77 -0
- jolt/pkgs/pugixml.py +27 -0
- jolt/pkgs/python.py +19 -0
- jolt/pkgs/qt.py +35 -0
- jolt/pkgs/rapidjson.py +26 -0
- jolt/pkgs/rapidyaml.py +28 -0
- jolt/pkgs/re2.py +30 -0
- jolt/pkgs/re2c.py +17 -0
- jolt/pkgs/readline.py +15 -0
- jolt/pkgs/rust.py +41 -0
- jolt/pkgs/sdl.py +28 -0
- jolt/pkgs/simdjson.py +27 -0
- jolt/pkgs/soci.py +46 -0
- jolt/pkgs/spdlog.py +29 -0
- jolt/pkgs/spirv_llvm.py +21 -0
- jolt/pkgs/spirv_tools.py +24 -0
- jolt/pkgs/sqlite.py +83 -0
- jolt/pkgs/ssl.py +12 -0
- jolt/pkgs/texinfo.py +15 -0
- jolt/pkgs/tomlplusplus.py +22 -0
- jolt/pkgs/wayland.py +26 -0
- jolt/pkgs/x11.py +58 -0
- jolt/pkgs/xerces_c.py +20 -0
- jolt/pkgs/xorg.py +360 -0
- jolt/pkgs/xz.py +29 -0
- jolt/pkgs/yamlcpp.py +30 -0
- jolt/pkgs/zeromq.py +47 -0
- jolt/pkgs/zlib.py +69 -0
- jolt/pkgs/zstd.py +33 -0
- jolt/plugins/alias.py +3 -0
- jolt/plugins/allure.py +5 -2
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cache.py +133 -0
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/conan.py +238 -0
- jolt/plugins/cxx.py +698 -0
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/dashboard.py +1 -1
- jolt/plugins/docker.py +91 -23
- jolt/plugins/email.py +5 -2
- jolt/plugins/email.xslt +144 -101
- jolt/plugins/environ.py +11 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/gdb.py +44 -21
- jolt/plugins/gerrit.py +1 -14
- jolt/plugins/git.py +316 -101
- jolt/plugins/googletest.py +522 -1
- jolt/plugins/http.py +36 -38
- jolt/plugins/libtool.py +63 -0
- jolt/plugins/linux.py +990 -0
- jolt/plugins/logstash.py +4 -4
- jolt/plugins/meson.py +61 -0
- jolt/plugins/ninja-compdb.py +107 -31
- jolt/plugins/ninja.py +929 -134
- jolt/plugins/paths.py +11 -1
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/podman.py +148 -91
- jolt/plugins/python.py +137 -0
- jolt/plugins/remote_execution/__init__.py +0 -0
- jolt/plugins/remote_execution/administration_pb2.py +46 -0
- jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
- jolt/plugins/remote_execution/log_pb2.py +32 -0
- jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
- jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
- jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
- jolt/plugins/remote_execution/worker_pb2.py +38 -0
- jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
- jolt/plugins/report.py +12 -2
- jolt/plugins/rust.py +25 -0
- jolt/plugins/scheduler.py +710 -0
- jolt/plugins/selfdeploy/setup.py +9 -4
- jolt/plugins/selfdeploy.py +138 -88
- jolt/plugins/strings.py +35 -22
- jolt/plugins/symlinks.py +26 -11
- jolt/plugins/telemetry.py +5 -2
- jolt/plugins/timeline.py +13 -3
- jolt/plugins/volume.py +46 -48
- jolt/scheduler.py +591 -191
- jolt/tasks.py +1783 -245
- jolt/templates/export.sh.template +12 -6
- jolt/templates/timeline.html.template +44 -47
- jolt/timer.py +22 -0
- jolt/tools.py +749 -302
- jolt/utils.py +245 -18
- jolt/version.py +1 -1
- jolt/version_utils.py +2 -2
- jolt/xmldom.py +12 -2
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/METADATA +98 -38
- jolt-0.9.429.dist-info/RECORD +207 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/WHEEL +1 -1
- jolt/plugins/amqp.py +0 -834
- jolt/plugins/debian.py +0 -338
- jolt/plugins/ftp.py +0 -181
- jolt/plugins/ninja-cache.py +0 -64
- jolt/plugins/ninjacli.py +0 -271
- jolt/plugins/repo.py +0 -253
- jolt-0.9.76.dist-info/RECORD +0 -79
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/top_level.txt +0 -0
jolt/utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import contextlib
|
|
2
|
+
import ctypes
|
|
2
3
|
import fnmatch
|
|
3
4
|
import re
|
|
4
5
|
import time
|
|
@@ -10,6 +11,9 @@ import os
|
|
|
10
11
|
import hashlib
|
|
11
12
|
from fasteners import lock, process_lock
|
|
12
13
|
import json
|
|
14
|
+
import platform
|
|
15
|
+
import signal
|
|
16
|
+
import threading
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
read_input = input
|
|
@@ -27,9 +31,9 @@ locked = lock.locked
|
|
|
27
31
|
|
|
28
32
|
def is_str(s):
|
|
29
33
|
try:
|
|
30
|
-
return type(s)
|
|
34
|
+
return type(s) is str or type(s) is unicode
|
|
31
35
|
except NameError:
|
|
32
|
-
return type(s)
|
|
36
|
+
return type(s) is str
|
|
33
37
|
|
|
34
38
|
|
|
35
39
|
def decode_str(s):
|
|
@@ -55,7 +59,9 @@ def decorate_prepend(func, extra_func):
|
|
|
55
59
|
|
|
56
60
|
|
|
57
61
|
def as_list(t):
|
|
58
|
-
|
|
62
|
+
if t is None:
|
|
63
|
+
return []
|
|
64
|
+
return [t] if type(t) is str or not is_iterable(t) else list(t)
|
|
59
65
|
|
|
60
66
|
|
|
61
67
|
def is_iterable(x):
|
|
@@ -68,9 +74,9 @@ def is_iterable(x):
|
|
|
68
74
|
|
|
69
75
|
|
|
70
76
|
def as_stable_string_list(o):
|
|
71
|
-
if type(o)
|
|
77
|
+
if type(o) is list or type(o) is tuple:
|
|
72
78
|
return sorted([str(item) for item in o])
|
|
73
|
-
elif type(o)
|
|
79
|
+
elif type(o) is dict:
|
|
74
80
|
return sorted(["{0}={1}".format(key, as_stable_string_list(val))
|
|
75
81
|
for key, val in o.items()])
|
|
76
82
|
else:
|
|
@@ -78,13 +84,13 @@ def as_stable_string_list(o):
|
|
|
78
84
|
|
|
79
85
|
|
|
80
86
|
def as_stable_tuple_list(o):
|
|
81
|
-
assert type(o)
|
|
87
|
+
assert type(o) is dict, "as_stable_tuple_list: argument is not a dict"
|
|
82
88
|
list = [(key, value) for key, value in o.items()]
|
|
83
89
|
return sorted(list, key=lambda x: x[0])
|
|
84
90
|
|
|
85
91
|
|
|
86
92
|
def as_human_size(size):
|
|
87
|
-
unit_precision = [("B", 0), ("
|
|
93
|
+
unit_precision = [("B", 0), ("KiB", 0), ("MiB", 1), ("GiB", 2), ("TiB", 2), ("PiB", 2), ("EiB", 2)]
|
|
88
94
|
index = 0
|
|
89
95
|
while size > 1024:
|
|
90
96
|
size /= 1024
|
|
@@ -125,12 +131,13 @@ def call_and_catch_and_log(f, *args, **kwargs):
|
|
|
125
131
|
|
|
126
132
|
|
|
127
133
|
def parse_aliased_task_name(name):
|
|
128
|
-
match = re.match(r"^((?P<alias>[^=:]+)=)?(?P<task>[^:]+)(:(?P<params>.*))?$", name)
|
|
134
|
+
match = re.match(r"^((?P<alias>[^=:]+)=)?((?P<artifact>[^@=:]+)@)?(?P<task>[^:]+)(:(?P<params>.*))?$", name)
|
|
129
135
|
if not match:
|
|
130
136
|
from jolt.error import raise_error
|
|
131
137
|
raise_error("Illegal task name: {}", name)
|
|
132
138
|
match = match.groupdict()
|
|
133
139
|
alias = match["alias"]
|
|
140
|
+
artifact = match["artifact"]
|
|
134
141
|
task = match["task"]
|
|
135
142
|
params = match["params"] or {}
|
|
136
143
|
|
|
@@ -146,15 +153,17 @@ def parse_aliased_task_name(name):
|
|
|
146
153
|
|
|
147
154
|
params = {key: value for key, value in map(_param, params) if key}
|
|
148
155
|
|
|
149
|
-
return alias, task, params
|
|
156
|
+
return alias, artifact, task, params
|
|
150
157
|
|
|
151
158
|
|
|
152
159
|
def parse_task_name(name):
|
|
153
|
-
_, task, params = parse_aliased_task_name(name)
|
|
160
|
+
_, _, task, params = parse_aliased_task_name(name)
|
|
154
161
|
return task, params
|
|
155
162
|
|
|
156
163
|
|
|
157
|
-
def format_task_name(name, params):
|
|
164
|
+
def format_task_name(name, params, artifact=None):
|
|
165
|
+
if artifact:
|
|
166
|
+
name = f"{artifact}@{name}"
|
|
158
167
|
if not params:
|
|
159
168
|
return name
|
|
160
169
|
|
|
@@ -210,8 +219,14 @@ class _SafeDict(object):
|
|
|
210
219
|
value = self.values.get(key)
|
|
211
220
|
if value is None:
|
|
212
221
|
value = call_and_catch(getattr, self.values.get("_instance", object()), key)
|
|
222
|
+
if value is None and key == "buildroot":
|
|
223
|
+
tools = getattr(self.values.get("_instance", object()), "tools", None)
|
|
224
|
+
if tools:
|
|
225
|
+
value = tools.buildroot
|
|
213
226
|
if value is None:
|
|
214
227
|
value = self._envget(key)
|
|
228
|
+
if type(value) is list:
|
|
229
|
+
value = " ".join(value)
|
|
215
230
|
if value is not None:
|
|
216
231
|
return value
|
|
217
232
|
if self.errors:
|
|
@@ -227,6 +242,10 @@ class JoltFormatter(Formatter):
|
|
|
227
242
|
return str(value).lower()
|
|
228
243
|
elif conversion == "c":
|
|
229
244
|
return value()
|
|
245
|
+
elif conversion == "t":
|
|
246
|
+
return str(value).title()
|
|
247
|
+
elif conversion == "j":
|
|
248
|
+
return " ".join(value)
|
|
230
249
|
return super().convert_field(value, conversion)
|
|
231
250
|
|
|
232
251
|
|
|
@@ -293,7 +312,7 @@ class duration_diff(object):
|
|
|
293
312
|
if isinstance(dur, duration):
|
|
294
313
|
now = duration()
|
|
295
314
|
self._elapsed += dur.diff(now)._elapsed
|
|
296
|
-
if type(dur)
|
|
315
|
+
if type(dur) is int:
|
|
297
316
|
self._elapsed += dur
|
|
298
317
|
return self
|
|
299
318
|
|
|
@@ -307,19 +326,24 @@ class cached:
|
|
|
307
326
|
|
|
308
327
|
@staticmethod
|
|
309
328
|
def instance(f):
|
|
329
|
+
f.__cached_mutex = RLock()
|
|
330
|
+
|
|
310
331
|
def _f(self, *args, **kwargs):
|
|
311
332
|
attr = "__cached_result_" + str(id(f))
|
|
312
|
-
with
|
|
333
|
+
with f.__cached_mutex:
|
|
313
334
|
if not hasattr(self, attr):
|
|
314
335
|
setattr(self, attr, f(self, *args, **kwargs))
|
|
315
336
|
return getattr(self, attr)
|
|
337
|
+
|
|
316
338
|
return _f
|
|
317
339
|
|
|
318
340
|
@staticmethod
|
|
319
341
|
def method(f):
|
|
342
|
+
f.__cached_mutex = RLock()
|
|
343
|
+
|
|
320
344
|
def _f(*args, **kwargs):
|
|
321
345
|
attr = "__cached_result_" + str(id(f))
|
|
322
|
-
with
|
|
346
|
+
with f.__cached_mutex:
|
|
323
347
|
if not hasattr(f, attr):
|
|
324
348
|
setattr(f, attr, f(*args, **kwargs))
|
|
325
349
|
return getattr(f, attr)
|
|
@@ -351,6 +375,73 @@ def ignore_exception(exc=Exception):
|
|
|
351
375
|
return contextlib.suppress(exc)
|
|
352
376
|
|
|
353
377
|
|
|
378
|
+
class SignalHandler(object):
|
|
379
|
+
def __init__(self, signum):
|
|
380
|
+
self.original_handler = signal.signal(signum, self._handler)
|
|
381
|
+
self.handlers = []
|
|
382
|
+
|
|
383
|
+
def _handler(self, signum, frame):
|
|
384
|
+
for handler in self.handlers:
|
|
385
|
+
handler.add_signal(signum, frame)
|
|
386
|
+
if not self.handlers and self.original_handler:
|
|
387
|
+
self.original_handler(signum, frame)
|
|
388
|
+
|
|
389
|
+
def new_monitor(self):
|
|
390
|
+
class Finalizer(object):
|
|
391
|
+
def __init__(self, handler):
|
|
392
|
+
self.handler = handler
|
|
393
|
+
self.signals = []
|
|
394
|
+
|
|
395
|
+
def add_signal(self, signum, frame):
|
|
396
|
+
self.signals.append((signum, frame))
|
|
397
|
+
|
|
398
|
+
def __call__(self):
|
|
399
|
+
self.handler.handlers.remove(self)
|
|
400
|
+
for signum, frame in self.signals:
|
|
401
|
+
self.handler.original_handler(signum, frame)
|
|
402
|
+
|
|
403
|
+
finalizer = Finalizer(self)
|
|
404
|
+
self.handlers.append(finalizer)
|
|
405
|
+
return finalizer
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
sigint_handler = SignalHandler(signal.SIGINT)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@contextlib.contextmanager
|
|
412
|
+
def delayed_signal(signum):
|
|
413
|
+
""" A context manager that delays signals until after the code block. """
|
|
414
|
+
|
|
415
|
+
finalize = sigint_handler.new_monitor()
|
|
416
|
+
try:
|
|
417
|
+
yield
|
|
418
|
+
finally:
|
|
419
|
+
finalize()
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
@contextlib.contextmanager
|
|
423
|
+
def delayed_interrupt():
|
|
424
|
+
if hasattr(signal, 'pthread_sigmask'):
|
|
425
|
+
try:
|
|
426
|
+
# Temporarily block the SIGINT signal
|
|
427
|
+
signal.pthread_sigmask(signal.SIG_BLOCK, {signal.SIGINT})
|
|
428
|
+
yield
|
|
429
|
+
finally:
|
|
430
|
+
# Unblock the SIGINT signal after the code block
|
|
431
|
+
signal.pthread_sigmask(signal.SIG_UNBLOCK, {signal.SIGINT})
|
|
432
|
+
else:
|
|
433
|
+
# Fallback for systems without pthread_sigmask
|
|
434
|
+
yield
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def delay_interrupt(func):
|
|
438
|
+
@wraps(func)
|
|
439
|
+
def _f(*args, **kwargs):
|
|
440
|
+
with delayed_interrupt():
|
|
441
|
+
return func(*args, **kwargs)
|
|
442
|
+
return _f
|
|
443
|
+
|
|
444
|
+
|
|
354
445
|
def Singleton(cls):
|
|
355
446
|
cls._instance = None
|
|
356
447
|
|
|
@@ -364,6 +455,28 @@ def Singleton(cls):
|
|
|
364
455
|
return cls
|
|
365
456
|
|
|
366
457
|
|
|
458
|
+
class IdLock(object):
|
|
459
|
+
""" A wrapper for multiple thread locks that are identified by a unique id. """
|
|
460
|
+
|
|
461
|
+
def __init__(self):
|
|
462
|
+
self._lock = RLock()
|
|
463
|
+
self._locks = {}
|
|
464
|
+
|
|
465
|
+
def acquire(self, id, blocking=True):
|
|
466
|
+
with self._lock:
|
|
467
|
+
if id not in self._locks:
|
|
468
|
+
self._locks[id] = RLock()
|
|
469
|
+
lock = self._locks[id]
|
|
470
|
+
return lock.acquire(blocking=blocking)
|
|
471
|
+
|
|
472
|
+
def release(self, id):
|
|
473
|
+
with self._lock:
|
|
474
|
+
if id in self._locks:
|
|
475
|
+
self._locks[id].release()
|
|
476
|
+
else:
|
|
477
|
+
raise RuntimeError("Lock not acquired: {}".format(id))
|
|
478
|
+
|
|
479
|
+
|
|
367
480
|
class LockFile(object):
|
|
368
481
|
def __init__(self, path, logfunc=None, *args, **kwargs):
|
|
369
482
|
self._file = process_lock.InterProcessLock(os.path.join(path, "lock"))
|
|
@@ -438,14 +551,31 @@ def tojson(filepath, data, ignore_errors=False, indent=2):
|
|
|
438
551
|
|
|
439
552
|
def concat_attributes(attrib, postfix, prepend=False):
|
|
440
553
|
def _decorate(cls):
|
|
441
|
-
_orig = getattr(cls, "_" + attrib, lambda self:
|
|
554
|
+
_orig = getattr(cls, "_" + attrib, lambda self: getattr(self, attrib, None))
|
|
442
555
|
|
|
443
556
|
def _get(self):
|
|
444
557
|
orig = _orig(self)
|
|
445
|
-
if
|
|
446
|
-
|
|
558
|
+
if attrib != postfix:
|
|
559
|
+
appended = getattr(self, self.expand(postfix), type(orig)() if orig is not None else [])
|
|
447
560
|
else:
|
|
448
|
-
|
|
561
|
+
appended = type(orig)() if orig is not None else []
|
|
562
|
+
|
|
563
|
+
if orig is None:
|
|
564
|
+
orig = type(appended)()
|
|
565
|
+
|
|
566
|
+
assert type(orig) is type(appended), \
|
|
567
|
+
f"Cannot append attributes '{attrib}' and '{postfix}': mismatching type"
|
|
568
|
+
|
|
569
|
+
assert type(orig) is list or type(orig) is dict, \
|
|
570
|
+
f"Cannot append attributes '{attrib}' and '{postfix}': unsupported type '{type(orig)}'"
|
|
571
|
+
|
|
572
|
+
if type(orig) is dict:
|
|
573
|
+
value = orig | appended
|
|
574
|
+
|
|
575
|
+
if type(appended) is list:
|
|
576
|
+
value = orig + appended if not prepend else appended + orig
|
|
577
|
+
|
|
578
|
+
return value
|
|
449
579
|
|
|
450
580
|
setattr(cls, "_" + attrib, _get)
|
|
451
581
|
return cls
|
|
@@ -484,3 +614,100 @@ def quote(value, char='"'):
|
|
|
484
614
|
|
|
485
615
|
def option(prefix, value):
|
|
486
616
|
return "{}{}".format(prefix, quote(value)) if value else ""
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def shorten(string, count=30):
|
|
620
|
+
if len(string) > count:
|
|
621
|
+
keep = int(count / 2 - 1)
|
|
622
|
+
if keep <= 0:
|
|
623
|
+
keep = 1
|
|
624
|
+
return string[:keep] + "..." + string[-keep + 1:]
|
|
625
|
+
return string
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def prefix(value, pfx):
|
|
629
|
+
if type(value) is list:
|
|
630
|
+
return [pfx + item for item in value]
|
|
631
|
+
return pfx + value
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
def suffix(value, sfx):
|
|
635
|
+
if type(value) is list:
|
|
636
|
+
return [item + sfx for item in value]
|
|
637
|
+
return value + sfx
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def hostname():
|
|
641
|
+
""" Returns the hostname of the machine. """
|
|
642
|
+
import socket
|
|
643
|
+
return socket.gethostname()
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
def timeout(seconds, exception_type):
|
|
647
|
+
""" A context manager that enforces a timeout.
|
|
648
|
+
|
|
649
|
+
If the block of code takes longer than the specified timeout,
|
|
650
|
+
the context manager will raise an asyncronous TimeoutError.
|
|
651
|
+
"""
|
|
652
|
+
|
|
653
|
+
class TimeoutContext(object):
|
|
654
|
+
def __init__(self, timeout, exception_type):
|
|
655
|
+
self._timer = threading.Timer(timeout, self._raise_timeout)
|
|
656
|
+
self._tid = threading.current_thread().ident
|
|
657
|
+
self._exc = exception_type
|
|
658
|
+
|
|
659
|
+
def _raise_timeout(self):
|
|
660
|
+
tid = ctypes.c_ulong(self._tid)
|
|
661
|
+
ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(
|
|
662
|
+
tid, ctypes.py_object(self._exc))
|
|
663
|
+
|
|
664
|
+
if ret == 0:
|
|
665
|
+
raise ValueError("Invalid thread ID {self._tid}")
|
|
666
|
+
elif ret > 1:
|
|
667
|
+
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
|
|
668
|
+
raise SystemError("PyThreadState_SetAsyncExc failed")
|
|
669
|
+
|
|
670
|
+
def __enter__(self):
|
|
671
|
+
self._timer.start()
|
|
672
|
+
return self
|
|
673
|
+
|
|
674
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
675
|
+
self._timer.cancel()
|
|
676
|
+
return None
|
|
677
|
+
|
|
678
|
+
return TimeoutContext(seconds, exception_type)
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
def platform_os_arch():
|
|
682
|
+
"""
|
|
683
|
+
Returns the name of the operating system and architecture.
|
|
684
|
+
|
|
685
|
+
The values match the GOOS and GOARCH environment variables used by Go.
|
|
686
|
+
"""
|
|
687
|
+
_ARCHITECTURE_DICT = {
|
|
688
|
+
"Windows": {
|
|
689
|
+
"AMD64": "amd64",
|
|
690
|
+
"X86": "386",
|
|
691
|
+
"ARM64": "arm64",
|
|
692
|
+
},
|
|
693
|
+
"Linux": {
|
|
694
|
+
"x86_64": "amd64",
|
|
695
|
+
"i686": "386",
|
|
696
|
+
"i386": "386",
|
|
697
|
+
"aarch64": "arm64",
|
|
698
|
+
"armv7l": "armv7",
|
|
699
|
+
},
|
|
700
|
+
"Darwin": {
|
|
701
|
+
"x86_64": "amd64",
|
|
702
|
+
"arm64": "arm64",
|
|
703
|
+
},
|
|
704
|
+
}
|
|
705
|
+
uname = platform.uname()
|
|
706
|
+
try:
|
|
707
|
+
system = uname.system.lower()
|
|
708
|
+
architecture = _ARCHITECTURE_DICT[uname.system][uname.machine]
|
|
709
|
+
except KeyError:
|
|
710
|
+
raise RuntimeError(
|
|
711
|
+
f"Unsupported platform: {uname.system} {uname.machine}"
|
|
712
|
+
) from None
|
|
713
|
+
return system, architecture
|
jolt/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.9.
|
|
1
|
+
__version__ = "0.9.429"
|
jolt/version_utils.py
CHANGED
|
@@ -4,7 +4,7 @@ import re
|
|
|
4
4
|
|
|
5
5
|
class version(object):
|
|
6
6
|
def __init__(self, verstr):
|
|
7
|
-
if type(verstr)
|
|
7
|
+
if type(verstr) is str:
|
|
8
8
|
match = re.search(r"(?P<major>[\d]+)\.(?P<minor>[\d]+)(\.(?P<patch>[\d]+))?", verstr)
|
|
9
9
|
if not match:
|
|
10
10
|
raise ValueError(verstr)
|
|
@@ -12,7 +12,7 @@ class version(object):
|
|
|
12
12
|
self.major = int(values["major"])
|
|
13
13
|
self.minor = int(values["minor"])
|
|
14
14
|
self.patch = int(values["patch"]) if values["patch"] else None
|
|
15
|
-
elif type(verstr)
|
|
15
|
+
elif type(verstr) is tuple:
|
|
16
16
|
if len(verstr) < 2 or len(verstr) > 3:
|
|
17
17
|
raise ValueError(verstr)
|
|
18
18
|
self.major = verstr[0]
|
jolt/xmldom.py
CHANGED
|
@@ -49,6 +49,9 @@ class SubElement(object):
|
|
|
49
49
|
def iter(self, *args, **kwargs):
|
|
50
50
|
return self._elem.iter(*args, **kwargs)
|
|
51
51
|
|
|
52
|
+
def remove(self, *args, **kwargs):
|
|
53
|
+
return self._elem.remove(*args, **kwargs)
|
|
54
|
+
|
|
52
55
|
|
|
53
56
|
class Attribute(object):
|
|
54
57
|
def __init__(self, attribute, varname=None, child=False, values=None, base64=False, zlib=False):
|
|
@@ -147,8 +150,8 @@ class Composition(object):
|
|
|
147
150
|
self.append(child)
|
|
148
151
|
return child
|
|
149
152
|
|
|
150
|
-
def remove(self,
|
|
151
|
-
self.remove(
|
|
153
|
+
def remove(self, *args, **kwargs):
|
|
154
|
+
self.remove(*args, **kwargs)
|
|
152
155
|
|
|
153
156
|
@property
|
|
154
157
|
def get(self):
|
|
@@ -156,6 +159,13 @@ class Composition(object):
|
|
|
156
159
|
children = [n for n in children if n.tag == name]
|
|
157
160
|
return [comp_cls(elem=child) for child in children]
|
|
158
161
|
|
|
162
|
+
def clear(self):
|
|
163
|
+
children = list(self.getroot()) if isinstance(self, ElementTree) else list(self._elem)
|
|
164
|
+
children = [n for n in children if n.tag == name]
|
|
165
|
+
for child in children:
|
|
166
|
+
getattr(self, "remove_" + name)(child)
|
|
167
|
+
|
|
168
|
+
setattr(cls, 'clear_' + name + "s", clear)
|
|
159
169
|
setattr(cls, 'create_' + name, create)
|
|
160
170
|
setattr(cls, 'remove_' + name, remove)
|
|
161
171
|
setattr(cls, name + 's', get)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: jolt
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.429
|
|
4
4
|
Summary: A task executor
|
|
5
5
|
Home-page: https://github.com/srand/jolt
|
|
6
6
|
Author: Robert Andersson
|
|
@@ -20,47 +20,107 @@ Classifier: Programming Language :: C++
|
|
|
20
20
|
Classifier: Programming Language :: Java
|
|
21
21
|
Classifier: Programming Language :: JavaScript
|
|
22
22
|
Classifier: Programming Language :: Python :: 3
|
|
23
|
-
Requires-
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist:
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist:
|
|
49
|
-
Requires-Dist:
|
|
50
|
-
Requires-Dist:
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Requires-Dist: Jinja2==3.1.4
|
|
25
|
+
Requires-Dist: Jinja2==3.1.4
|
|
26
|
+
Requires-Dist: MarkupSafe==2.1.5
|
|
27
|
+
Requires-Dist: PyJWT==2.9.0
|
|
28
|
+
Requires-Dist: PyYAML==6.0.2
|
|
29
|
+
Requires-Dist: PyYAML==6.0.2
|
|
30
|
+
Requires-Dist: Pygments==2.18.0
|
|
31
|
+
Requires-Dist: Pygments==2.18.0
|
|
32
|
+
Requires-Dist: SecretStorage==3.3.3
|
|
33
|
+
Requires-Dist: allure-python-commons==2.13.5
|
|
34
|
+
Requires-Dist: attrs==24.2.0
|
|
35
|
+
Requires-Dist: backports.tarfile==1.2.0
|
|
36
|
+
Requires-Dist: bottle==0.12.25
|
|
37
|
+
Requires-Dist: brotli==1.2.0
|
|
38
|
+
Requires-Dist: bz2file==0.98
|
|
39
|
+
Requires-Dist: certifi==2024.8.30
|
|
40
|
+
Requires-Dist: cffi==1.17.1
|
|
41
|
+
Requires-Dist: charset-normalizer==3.3.2
|
|
42
|
+
Requires-Dist: click==8.1.7
|
|
43
|
+
Requires-Dist: colorama==0.4.6
|
|
44
|
+
Requires-Dist: conan==2.10.2
|
|
45
|
+
Requires-Dist: cryptography==43.0.1
|
|
46
|
+
Requires-Dist: distro==1.8.0
|
|
47
|
+
Requires-Dist: docutils==0.21.2
|
|
48
|
+
Requires-Dist: fasteners==0.19
|
|
49
|
+
Requires-Dist: flake8==7.1.1
|
|
50
|
+
Requires-Dist: grpcio==1.66.1
|
|
51
|
+
Requires-Dist: idna==3.10
|
|
52
|
+
Requires-Dist: importlib_metadata==8.5.0
|
|
53
|
+
Requires-Dist: importlib_metadata==8.5.0
|
|
54
|
+
Requires-Dist: inflate64==1.0.4
|
|
55
|
+
Requires-Dist: jaraco.classes==3.4.0
|
|
56
|
+
Requires-Dist: jaraco.context==6.0.1
|
|
57
|
+
Requires-Dist: jaraco.functools==4.0.2
|
|
58
|
+
Requires-Dist: jeepney==0.8.0
|
|
59
|
+
Requires-Dist: keyring==25.4.1
|
|
60
|
+
Requires-Dist: keyrings.alt==5.0.2
|
|
61
|
+
Requires-Dist: lxml==5.3.0
|
|
62
|
+
Requires-Dist: markdown-it-py==3.0.0
|
|
63
|
+
Requires-Dist: mccabe==0.7.0
|
|
64
|
+
Requires-Dist: more-itertools==10.5.0
|
|
65
|
+
Requires-Dist: more-itertools==10.5.0
|
|
66
|
+
Requires-Dist: multi_key_dict==2.0.3
|
|
67
|
+
Requires-Dist: multivolumefile==0.2.3
|
|
68
|
+
Requires-Dist: nh3==0.2.19
|
|
69
|
+
Requires-Dist: ninja==1.11.1.1
|
|
70
|
+
Requires-Dist: packaging==24.2
|
|
71
|
+
Requires-Dist: patch-ng==1.18.1
|
|
72
|
+
Requires-Dist: pip==25.3
|
|
73
|
+
Requires-Dist: pkginfo==1.12.0
|
|
74
|
+
Requires-Dist: pluggy==1.5.0
|
|
75
|
+
Requires-Dist: pluginbase==1.0.1
|
|
76
|
+
Requires-Dist: protobuf==5.28.2
|
|
77
|
+
Requires-Dist: psutil==6.0.0
|
|
78
|
+
Requires-Dist: py7zr==1.0.0
|
|
79
|
+
Requires-Dist: pybcj==1.0.6
|
|
80
|
+
Requires-Dist: pycodestyle==2.12.1
|
|
81
|
+
Requires-Dist: pycparser==2.22
|
|
82
|
+
Requires-Dist: pycryptodomex==3.23.0
|
|
83
|
+
Requires-Dist: pyflakes==3.2.0
|
|
84
|
+
Requires-Dist: pygit2==1.15.1
|
|
85
|
+
Requires-Dist: pyppmd==1.2.0
|
|
86
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
87
|
+
Requires-Dist: pyzstd==0.18.0
|
|
88
|
+
Requires-Dist: readme_renderer==44.0
|
|
89
|
+
Requires-Dist: requests-toolbelt==1.0.0
|
|
90
|
+
Requires-Dist: requests==2.32.3
|
|
91
|
+
Requires-Dist: rfc3986==2.0.0
|
|
92
|
+
Requires-Dist: rich==13.9.4
|
|
93
|
+
Requires-Dist: setuptools==80.9.0
|
|
94
|
+
Requires-Dist: six==1.16.0
|
|
95
|
+
Requires-Dist: texttable==1.7.0
|
|
96
|
+
Requires-Dist: tqdm==4.66.5
|
|
97
|
+
Requires-Dist: twine==6.0.1
|
|
98
|
+
Requires-Dist: typing_extensions==4.15.0
|
|
99
|
+
Requires-Dist: urllib3==1.26.20
|
|
100
|
+
Requires-Dist: wheel==0.45.1
|
|
101
|
+
Requires-Dist: zipp==3.20.2
|
|
102
|
+
Requires-Dist: zstandard==0.23.0
|
|
51
103
|
Provides-Extra: allure
|
|
52
|
-
Requires-Dist: allure-python-commons
|
|
53
|
-
Provides-Extra: amqp
|
|
54
|
-
Requires-Dist: pika ; extra == 'amqp'
|
|
104
|
+
Requires-Dist: allure-python-commons; extra == "allure"
|
|
55
105
|
Provides-Extra: conan
|
|
56
|
-
Requires-Dist: conan
|
|
106
|
+
Requires-Dist: conan>=2.0; extra == "conan"
|
|
57
107
|
Provides-Extra: dev
|
|
58
|
-
Requires-Dist: check-manifest
|
|
108
|
+
Requires-Dist: check-manifest; extra == "dev"
|
|
59
109
|
Provides-Extra: doc
|
|
60
|
-
Requires-Dist: sphinx-click
|
|
61
|
-
Requires-Dist: sphinx-rtd-theme
|
|
110
|
+
Requires-Dist: sphinx-click; extra == "doc"
|
|
111
|
+
Requires-Dist: sphinx-rtd-theme; extra == "doc"
|
|
62
112
|
Provides-Extra: test
|
|
63
|
-
Requires-Dist: coverage
|
|
113
|
+
Requires-Dist: coverage; extra == "test"
|
|
114
|
+
Dynamic: author
|
|
115
|
+
Dynamic: author-email
|
|
116
|
+
Dynamic: classifier
|
|
117
|
+
Dynamic: description
|
|
118
|
+
Dynamic: home-page
|
|
119
|
+
Dynamic: keywords
|
|
120
|
+
Dynamic: provides-extra
|
|
121
|
+
Dynamic: requires-dist
|
|
122
|
+
Dynamic: requires-python
|
|
123
|
+
Dynamic: summary
|
|
64
124
|
|
|
65
125
|
Jolt
|
|
66
126
|
============================
|