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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 | #
# In practice there's little need for full-blown dependency resolving
# for application-level modules.
#
class dependency(object):
# prepare list of known plugins and versions
def __init__(self, core={}):
self.have = {}.update(core)
self.have = all_plugin_meta()
# dependencies on core modules are somewhat more interesting:
for name in ("st2", "uikit", "config", "action"):
self.have[name] = plugin_meta(module=name, extra_base=["config"])
self.have["streamtuner2"] = self.have["st2"]
have = {}
# depends:
def depends(self, plugin):
if plugin.get("depends"):
d = self.deps(plugin["depends"])
if not self.cmp(d, self.have):
return False
return True
# basic list pre-filtering (skip __init__, filter by api:,
# exclude installed & same-version plugins)
def valid(self, newpl):
id = newpl.get("$name", "__invalid")
have_ver = self.have.get(id, {}).get("version", "0")
if id.find("__") == 0:
pass
elif newpl.get("api") not in ("python", "streamtuner2"):
pass
elif set((newpl.get("status"), newpl.get("priority"))).intersection(set(("obsolete", "broken"))):
pass
elif have_ver >= newpl.get("version", "0.0"):
pass
else:
return True
# Split trivial "pkg, mod >= 1, uikit < 4.0" list
def deps(self, dep_str):
d = []
for dep in re.split(r"\s*[,;]+\s*", dep_str):
# skip deb:pkg-name, rpm:name, bin:name etc.
if not len(dep) or dep.find(":") >= 0:
continue
# find comparison and version num
dep += " >= 0"
m = re.search(r"([\w.-]+)\s*([>=<!~]+)\s*([\d.]+([-~.]\w+)*)", dep)
if m and m.group(2):
d.append([m.group(i) for i in (1, 2, 3)])
return d
# Do actual comparison
def cmp(self, d, have):
r = True
for name, op, ver in d:
# skip unknown plugins, might be python module references
if not have.get(name, {}).get("version"):
continue
curr = have[name]["version"]
tbl = {
">=": curr >= ver,
"<=": curr <= ver,
"==": curr == ver,
">": curr > ver,
"<": curr < ver,
"!=": curr != ver,
}
#log.VERSION_COMPARE(name, " → (", curr, op, ver, ") == ", r)
r &= tbl.get(op, True)
return r
# Add plugin defaults to conf.* store
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Utility function which applies plugin meta data to a config
# store. Which in the case of streamtuner2 is really just a |
|
|
>
>
>
>
>
>
>
>
>
|
|
|
>
|
>
>
|
|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
>
|
<
>
| 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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489 | #
# In practice there's little need for full-blown dependency resolving
# for application-level modules.
#
class dependency(object):
# prepare list of known plugins and versions
def __init__(self, add={}, core=["st2", "uikit", "config", "action"]):
self.have = {
"python": { "version": sys.version }
}
# inject virtual modules
for name, meta in add.items():
if isinstance(meta, bool): meta = 1 if meta else -1
if isinstance(meta, tuple): meta = ".".join(str(n) for n in meta)
if isinstance(meta, (int, float, str)): meta = {"version": str(meta)}
self.have[name] = meta
# read plugins/*
self.have.update(all_plugin_meta())
# add core modules
for name in core:
self.have[name] = plugin_meta(module=name, extra_base=["config"])
# aliases
for name, meta in self.have.items():
if meta.get("alias"):
for alias in re.split("\s*[,;]\s*", meta["alias"]):
self.have[alias] = self.have[name]
# depends:
def depends(self, plugin):
if plugin.get("depends"):
dep_cmp = self.deps(plugin["depends"])
if not (True in [self.cmp(alt_cmp, self.have) for alt_cmp in dep_cmp]):
return False
return True
# basic list pre-filtering (skip __init__, filter by api:,
# exclude installed & same-version plugins)
def valid(self, newpl):
id = newpl.get("$name", "__invalid")
have_ver = self.have.get(id, {}).get("version", "0")
if id.find("__") == 0:
pass
elif newpl.get("api") not in ("python", "streamtuner2"):
pass
elif set((newpl.get("status"), newpl.get("priority"))).intersection(set(("obsolete", "broken"))):
pass
elif have_ver >= newpl.get("version", "0.0"):
pass
else:
return True
# Split trivial "pkg | alt, mod >= 1, uikit < 4.0" string into nested list [[dep],[alt,alt],[dep]]
def deps(self, dep_str):
dep_cmp = []
for alt_str in re.split(r"\s*[,;]+\s*", dep_str):
alt_cmp = []
# split alternatives |
for part in re.split(r"\s*\|+\s*", alt_str):
# skip deb:pkg-name, rpm:name, bin:name etc.
if not len(part) or part.find(":") >= 0:
continue
# find comparison and version num
part += " >= 0"
m = re.search(r"([\w.-]+)\s*([>=<!~]+)\s*([\d.]+([-~.]\w+)*)", part)
if m and m.group(2):
alt_cmp.append([m.group(i) for i in (1, 2, 3)])
dep_cmp.append(alt_cmp)
return dep_cmp
# Do actual comparison
def cmp(self, d, have):
r = True
for name, op, ver in d:
# skip unknown plugins, might be python module references
if not have.get(name, {}).get("version"):
continue
curr = have[name]["version"]
tbl = {
">=": curr >= ver,
"<=": curr <= ver,
"==": curr == ver,
">": curr > ver,
"<": curr < ver,
"!=": curr != ver,
}
r &= tbl.get(op, True)
#print "log.VERSION_COMPARE: ", name, " → (", curr, op, ver, ") == ", r
return r
# Add plugin defaults to conf.* store
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Utility function which applies plugin meta data to a config
# store. Which in the case of streamtuner2 is really just a |