Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ branch:  streamtuner2


Check-in [a8ede6f518]

Overview
Comment:Updated to 0.7.3
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a8ede6f5181fcb66535b7efc7c0161f32569668c
User & Date: mario on 2020-12-12 15:10:20
Other Links: manifest | tags
Context
2020-12-12
15:11
Update configwin for select:{} being preparsed by pluginconf now check-in: 798a7746aa user: mario tags: trunk
15:10
Updated to 0.7.3 check-in: a8ede6f518 user: mario tags: trunk
15:10
Add uikit.get_bg_color() for TreeView search, but keep #ffffff for Gtk2 check-in: 2956305120 user: mario tags: trunk
Changes

Modified pluginconf.py from [8d185cdf67] to [d31c994508].

1

2
3
4

5
6
7




8
9
10
11
12
13
14

1
2
3

4
5
6

7
8
9
10
11
12
13
14
15
16
17
-
+


-
+


-
+
+
+
+







# encoding: UTF-8
# encoding: utf-8
# api: python
# type: extract
# category: io
# category: config
# title: Plugin configuration
# description: Read meta data, pyz/package contents, module locating
# version: 0.7.1
# version: 0.7.3
# state: stable
# classifiers: documentation
# license: PD
# priority: core
# docs: https://fossil.include-once.org/pluginspec/
# url: 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.
110
111
112
113
114
115
116
117

118
119
120
121

122
123
124
125
126
127
128
113
114
115
116
117
118
119

120
121
122
123

124
125
126
127
128
129
130
131







-
+



-
+









# Injectables
# ‾‾‾‾‾‾‾‾‾‾‾
log_ERR = lambda *x: None

# File lookup relation for get_data(), should name a top-level package.
module_base = "config"
module_base = "config"         # equivalent PluginBase(package=…)

# Package/module names for module_list() and plugin_meta() lookups.
# All associated paths will be scanned for module/plugin basenames.
plugin_base = ["channels"]
plugin_base = ["channels"]     # equivalent to `searchpath` in PluginBase


# Resource retrieval
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Fetches file content from install path or from within PYZ
# archive. This is just an alias and convenience wrapper for
# pkgutil.get_data().
308
309
310
311
312
313
314
315

316
317

318
319
320
321
322
323
324
311
312
313
314
315
316
317

318
319

320
321
322
323
324
325
326
327







-
+

-
+







# split up `select: 1=on|2=more|3=title` or `select: foo|bar|lists`
def config_opt_parse_select(s):
    if re.search("([=:])", s):
        return dict(rx.select_dict.findall(s))
    else:
        return dict([(v, v) for v in rx.select_list.findall(s)])

# normalize type:names to `str`, `bool`, `int`, `select`, `dict`
# normalize type:names to `str`, `text`, `bool`, `int`, `select`, `dict`
config_opt_type_map = dict(
    text="str", string="str", boolean="bool", checkbox="bool", integer="int", number="int",
    longstr="text", string="str", boolean="bool", checkbox="bool", integer="int", number="int",
    choice="select", options="select", table="dict", array="dict"
)


# Comment extraction regexps
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Pretty crude comment splitting approach. But works
338
339
340
341
342
343
344
345
346


347
348
349
350
351
352
353
341
342
343
344
345
346
347


348
349
350
351
352
353
354
355
356







-
-
+
+







        ["':$]?   (\w*)  ["']?                 # key or ":key" or '$key'
        \s* [:=] \s*                           # "=" or ":"
     (?:  "  ([^"]*)  "
       |  '  ([^']*)  '                        #  "quoted" or 'singl' values
       |     ([^,]*)                           #  or unquoted literals
     )
    """, re.X)
    select_dict = re.compile("(\w+)\s*[=:>]+\s*([^=,|:]+)")
    select_list = re.compile("\s*([^,|;]+)\s*")
    select_dict = re.compile(r"(\w+)\s*[=:>]+\s*([^=,|:]+)")
    select_list = re.compile(r"\s*([^,|;]+)\s*")



# ArgumentParser options conversion
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# As variation of in-application config: options, this method converts
# cmdline argument specifiers.
377
378
379
380
381
382
383
384

385
386
387
388
389
390




391
392
393
394
395
396
397
380
381
382
383
384
385
386

387
388
389




390
391
392
393
394
395
396
397
398
399
400







-
+


-
-
-
-
+
+
+
+







# meta['config'][] options to convert them.
#
def argparse_map(opt):
    if not ("arg" in opt and opt["name"] and opt["type"]):
        return {}

    # Extract --flag names
    args = opt["arg"].split() + re.findall("-+\w+", opt["name"])
    args = opt["arg"].split() + re.findall(r"-+\w+", opt["name"])

    # Prepare mapping options
    typing = re.findall("bool|str|\[\]|const|false|true", opt["type"])
    naming = re.findall("\[\]", opt["name"])
    name = re.findall("(?<!-)\\b\\w+", opt["name"])
    nargs = re.findall("\\b\d+\\b|[\?\*\+]", opt["type"]) or [None]
    typing = re.findall(r"bool|str|\[\]|const|false|true", opt["type"])
    naming = re.findall(r"\[\]", opt["name"])
    name = re.findall(r"(?<!-)\b\w+", opt["name"])
    nargs = re.findall(r"\b\d+\b|[\?\*\+]", opt["type"]) or [None]
    is_arr = "[]" in (naming + typing) and nargs == [None]
    is_bool = "bool" in typing
    false_b = "false" in typing or opt["value"] in ("0", "false")
    # print("\nname=", name, "is_arr=", is_arr, "is_bool=", is_bool,
    # "bool_d=", false_b, "naming=", naming, "typing=", typing)

    # Populate combination as far as ArgumentParser permits
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466







-
+







        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.copy().items():
            if meta.get("alias"):
                for alias in re.split("\s*[,;]\s*", meta["alias"]):
                for alias in re.split(r"\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, _log=lambda *x:0):
        id = newpl.get("$name", "__invalid")
        have_ver = self.have.get(id, {}).get("version", "0")
564
565
566
567
568
569
570
571
572


573
574

575
576
577
578
579




580
581
582
583
584
585
586
587
588
589
590
567
568
569
570
571
572
573


574
575
576

577
578




579
580
581
582
583
584
585
586
587
588
589
590
591
592
593







-
-
+
+

-
+

-
-
-
-
+
+
+
+











    # Option defaults, if not yet defined
    for opt in meta.get("config", []):
        if "name" in opt and "value" in opt:
            _value = opt.get("value", "")
            _name = opt.get("name")
            _type = opt.get("type")
            if _name not in conf_options:
                # typemap "bool" and "int" here
                if _type in ("bool", "boolean"):
                # typemap
                if _type == "bool":
                    val = _value.lower() in ("1", "true", "yes", "on")
                elif _type in ("int", "integer", "numeric"):
                elif _type == "int":
                    val = int(_value)
                elif _type in ("array", "table", "list"):
                    val = [ re.split("\s*[,;]\s*", s.strip()) for s in re.split("\s[|]\s*", _value) ]
                elif _type in ("dict"):
                    val = dict([ re.split("\s*(?:=>+|==*|-+>|:=+)\s*", s.strip()) for s in re.split("\s*[|;,]\s*", _value) ])
                elif _type in ("table", "list"):
                    val = [ re.split(r"\s*[,;]\s*", s.strip()) for s in re.split(r"\s*[|]\s*", _value) ]
                elif _type == "dict":
                    val = dict([ re.split(r"\s*(?:=>+|==*|-+>|:=+)\s*", s.strip(), 1) for s in re.split(r"\s*[|;,]\s*", _value) ])
                else:
                    val = str(_value)
                conf_options[_name] = val

    # Initial plugin activation status
    if module and module not in conf_plugins:
        conf_plugins[module] = meta.get("priority") in (
            "core", "builtin", "always", "default", "standard"
        )