Check-in [87e5798b35]
Overview
Comment: | Support for #depends: and #breaks:, and optionally bin:… and python:… checks. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
87e5798b35df481c1b8288b9b43732fb |
User & Date: | mario on 2017-01-02 20:48:09 |
Other Links: | manifest | tags |
Context
2017-01-03
| ||
20:11 | Introduce statusbar_img and GenericChannel.warn() function; albeit it allows any stock icon to be used. (May introduce a generalized background/foreground color wrapping.) check-in: 8b13ba0189 user: mario tags: trunk | |
2017-01-02
| ||
20:48 | Support for #depends: and #breaks:, and optionally bin:… and python:… checks. check-in: 87e5798b35 user: mario tags: trunk | |
20:47 | Guard empty streams["common"] dict. check-in: 4cbc0911f6 user: mario tags: trunk | |
Changes
Modified pluginconf.py from [edb9d7acf4] to [8ae013bd93].
1 2 3 4 5 6 | # encoding: UTF-8 # api: python # type: handler # category: io # title: Plugin configuration # description: Read meta data, pyz/package contents, module locating | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # encoding: UTF-8 # api: python # type: handler # category: io # title: Plugin configuration # description: Read meta data, pyz/package contents, module locating # version: 0.6.8 # priority: core # docs: http://fossil.include-once.org/streamtuner2/wiki/plugin+meta+data # config: - # # Provides plugin lookup and meta data extraction utility functions. # It's used to abstract module+option management in applications. # For consolidating internal use and external/tool accessibility. |
︙ | ︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import sys import os import re import pkgutil import inspect try: from compat2and3 import gzip_decode except: from gzip import decompress as gzip_decode # Py3 only import zipfile import argparse | > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | import sys import os import re import pkgutil import inspect from compat2and3 import find_executable try: from compat2and3 import gzip_decode except: from gzip import decompress as gzip_decode # Py3 only import zipfile import argparse |
︙ | ︙ | |||
416 417 418 419 420 421 422 | 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] | < < < < < < < < < < < < < | > > > > > > > > > | | > > | > | | | < | < > | > | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > | 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 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | 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] # basic plugin pre-screening (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 # Verify depends: and breaks: against existing plugins/modules def depends(self, plugin): r = True if plugin.get("depends"): r &= self.and_or(self.split(plugin["depends"]), self.have) if plugin.get("breaks"): r &= self.neither(self.split(plugin["breaks"]), self.have) return r # Split trivial "pkg | alt, mod >= 1, uikit < 4.0" string into nested list [[dep],[alt,alt],[dep]] def split(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): continue if part.find(":") >= 0: self.have[part] = { "version": self.module_test(*part.split(":")) } # find comparison and version num part += " >= 0" m = re.search(r"([\w.:-]+)\s*\(?\s*([>=<!~]+)\s*([\d.]+([-~.]\w+)*)", part) if m and m.group(2): alt_cmp.append([m.group(i) for i in (1, 2, 3)]) if alt_cmp: dep_cmp.append(alt_cmp) return dep_cmp # Single comparison def cmp(self, d, have, absent=True): name, op, ver = d # absent=True is the relaxed check, will ignore unknown plugins // set absent=False or None for strict check (as in breaks: rule e.g.) if not have.get(name, {}).get("version"): return absent # curr = installed version 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 # Compare nested structure of [[dep],[alt,alt]] def and_or(self, deps, have, r = True): #print deps return not False in [True in [self.cmp(d, have) for d in alternatives] for alternatives in deps] # Breaks/Conflicts: check [[or],[or]] def neither(self, deps, have): return not True in [self.cmp(d, have, absent=None) for cnd in deps for d in cnd] # Resolves/injects complex "bin:name" or "python:name" dependency URNs def module_test(self, type, name): return "1" # disabled for now if "_" + type in dir(self): return "1" if bool(getattr(self, "_" + type)(name)) else "-1" # `bin:name` lookup def _bin(self, name): return find_executable(name) # `python:module` test def _python(self, name): return __import__("imp").find_module(name) is not None # 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 # dictionary `conf{}` and a plugin list in `conf.plugins{}`. # |
︙ | ︙ |