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

⌈⌋ ⎇ branch:  streamtuner2


Diff

Differences From Artifact [2154593dfb]:

To Artifact [af23ce772a]:


1
2
3
4
5
6
7





8
9
10
11
12
13
14
#
# encoding: UTF-8
# api: streamtuner2
# type: class
# title: global config object
# description: reads ~/.config/streamtuner/*.json files
# config: {type:var, name:z, description:v}





#
# In the main application or module files which need access
# to a global conf.* object, just import this module as follows:
#
#   from config import *
#
# Here conf is already an instantiation of the underlying






|
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#
# encoding: UTF-8
# api: streamtuner2
# type: class
# title: global config object
# description: reads ~/.config/streamtuner/*.json files
# config:
#    { arg: -d,     type: str,      name: plugin[],  description: omit plugin from initialization  }
#    { arg: --gtk3, type: boolean,  name: gtk3,      description: use gtk3 interface }
#    { arg: -D,     type: boolean,  name: debug,     description: enable debug messages on console }
#    { arg: action, type: str*,     name: action[],  description: commandline actions }
#    { arg: -x,     type: boolean,  name: exit,      description: terminate right away }
#
# In the main application or module files which need access
# to a global conf.* object, just import this module as follows:
#
#   from config import *
#
# Here conf is already an instantiation of the underlying
27
28
29
30
31
32
33

34
35
36
37
38
39
40
import platform
import re
from compat2and3 import gzip_decode, find_executable
import zlib
import zipfile
import inspect
import pkgutil


# export symbols
__all__ = ["conf", "__print__", "dbg", "plugin_meta", "module_list", "get_data", "find_executable"]


#-- create a stub instance of config object
conf = object()







>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import platform
import re
from compat2and3 import gzip_decode, find_executable
import zlib
import zipfile
import inspect
import pkgutil
import argparse

# export symbols
__all__ = ["conf", "__print__", "dbg", "plugin_meta", "module_list", "get_data", "find_executable"]


#-- create a stub instance of config object
conf = object()
48
49
50
51
52
53
54

55
56
57
58
59
60
61
# Global configuration store
#
# Autointializes itself on startup, makes conf.vars available.
# Also provides .load() and .save() for JSON data/cache files.
#
class ConfigDict(dict):



    # start
    def __init__(self):
    
        # object==dict means conf.var is conf["var"]
        self.__dict__ = self  # let's pray this won't leak memory due to recursion issues








>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Global configuration store
#
# Autointializes itself on startup, makes conf.vars available.
# Also provides .load() and .save() for JSON data/cache files.
#
class ConfigDict(dict):

    args = {}

    # start
    def __init__(self):
    
        # object==dict means conf.var is conf["var"]
        self.__dict__ = self  # let's pray this won't leak memory due to recursion issues

73
74
75
76
77
78
79



80
81
82
83
84
85
86
                del last["share"]
            self.update(last)
            self.migrate()
        # store defaults in file
        else:
            self.save("settings")
            self.firstrun = 1





    # some defaults
    def defaults(self):
        self.play = {
           "audio/mpeg": self.find_player(),
           "audio/ogg": self.find_player(),







>
>
>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
                del last["share"]
            self.update(last)
            self.migrate()
        # store defaults in file
        else:
            self.save("settings")
            self.firstrun = 1
        
        # add argv
        self.args = self.init_args(argparse.ArgumentParser())


    # some defaults
    def defaults(self):
        self.play = {
           "audio/mpeg": self.find_player(),
           "audio/ogg": self.find_player(),
245
246
247
248
249
250
251
252







































253
254
255
256
257
258
259
                except:
                     netrc = parser(self.xdg() + "/netrc").hosts
            except:
                pass
        for server in varhosts:
            if server in netrc:
                return netrc[server]
        









































# Retrieve content from install path or pyzip archive (alias for pkgutil.get_data)
#
def get_data(fn, decode=False, gz=False, file_base="config"):
    try:
        bin = pkgutil.get_data(file_base, fn)







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
                except:
                     netrc = parser(self.xdg() + "/netrc").hosts
            except:
                pass
        for server in varhosts:
            if server in netrc:
                return netrc[server]

    # Use config: definitions for argv extraction
    def init_args(self, ap):
        for opt in plugin_meta(frame=0).get("config"):
            kwargs = self.argparse_map(opt)
            #print kwargs
            if kwargs:
                args = kwargs["args"]
                del kwargs["args"]
                ap.add_argument(*args, **kwargs)
        return ap.parse_args()

    # Transform config: description into quirky ArgumentParser list
    def argparse_map(self, 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"])

        # Prepare mapping options
        typing = re.findall("bool|str|\[\]|store|append|const", opt["type"])
        naming = re.findall("\[\]", opt["name"])
        name   = re.findall("(?<!-)\\b\\w+", opt["name"])
        nargs  = re.findall("\\b\d+\\b|\?|\*", opt["type"]) or [None]

        # Populate partially - ArgumentParser is highly fragile with combinations of named params
        kwargs = {
            "args": args,
            "dest": name[0] if not name[0] in args else None,
            "action": "append" if "[]" in (naming+typing) else ("store_true" if "bool" in typing else "store"),
            "nargs": nargs[0],
            "default": opt["value"],
           # "type":  int if "int" in typing else bool if "bool" in typing else str,
            "choices": opt["select"].split("|") if "select" in opt else None,
           # "required": "required" in opt,
            "help": opt["description"] or "",
        }
        return dict((k,w) for k,w in kwargs.items() if w is not None)



# Retrieve content from install path or pyzip archive (alias for pkgutil.get_data)
#
def get_data(fn, decode=False, gz=False, file_base="config"):
    try:
        bin = pkgutil.get_data(file_base, fn)