Index: config.py ================================================================== --- config.py +++ config.py @@ -3,15 +3,18 @@ # 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 } +# { arg: -d, type: str, name: disable[], description: Omit plugin from initialization. } +# { arg: -e, type: str, name: enable[], description: Add channel plugin. } +# { arg: --gtk3, type: boolean, name: gtk3, description: Start with Gtk3 interface. } +# { arg: -D, type: boolean, name: debug, description: Enable debug messages on console } +# { arg: action, type: str *, name: action[], description: CLI interface commands. } +# { arg: -x, type: boolean, name: exit, hidden: 1 } +# version: 2.5 +# priority: core # # In the main application or module files which need access # to a global conf.* object, just import this module as follows: # # from config import * @@ -22,11 +25,11 @@ # Also provides the logging function __print__, and basic # plugin handling code: plugin_meta() and module_list(), # and the relative get_data() alias (files from pyzip/path). # - +from __future__ import print_function import os import sys import json import gzip import platform @@ -85,10 +88,11 @@ self.save("settings") self.firstrun = 1 # add argv self.args = self.init_args(argparse.ArgumentParser()) + self.apply_args(self.args) # some defaults def defaults(self): self.play = { @@ -169,11 +173,13 @@ # store some configuration list/dict into a file def save(self, name="settings", data=None, gz=0, nice=0): name = name + ".json" if (data is None): - data = dict(self.__dict__) # ANOTHER WORKAROUND: typecast to plain dict(), else json filter_data sees it as object and str()s it + data = vars(self) + if "args" in data: + data.pop("args") nice = 1 # check for subdir if (name.find("/") > 0): subdir = name[0:name.find("/")] subdir = self.dir + "/" + subdir @@ -258,49 +264,83 @@ pass for server in varhosts: if server in netrc: return netrc[server] - # Use config: definitions for argv extraction + + # Use config:-style definitions for argv extraction, + # such as: { arg: -D, name: debug, type: bool } 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) + if [kwargs for kwargs in [self.argparse_map(opt)]]: + #print kwargs + ap.add_argument(*kwargs.pop("args"), **kwargs) return ap.parse_args() - # Transform config: description into quirky ArgumentParser list + + # Copy args fields into conf. dict + def apply_args(self, args): + self.debug = args.debug + if args.exit: + sys.exit(1) + for p_id in (args.disable or []): + self.plugins[p_id] = 0 + for p_id in (args.enable or []): + self.plugins[p_id] = 1 + + + # Transform config: description into quirky ArgumentParser args. + # + # · An option entry requires an arg: parameter - unlike regular plugin options: + # { arg: -i, name: input[], type: str, description: input files } + # · Where list elements are indicated by appending `[]` to names, or `*`onto type + # specifiers (alternatively `?`, `+` or a numeric count). + # · Types `str` or `int` and `bool` are recognized (bool with false/true optionals). + # · Entries can also carry a `hidden: 1` or `required: 1` attribute. + # · And `help:` is an alias to `description:` + # · Same for `default:` instead of the normal `value:` + # · And `type: select` utilizes the `select: a|b|c` format as uaual. + # · ArgParsers const=, metavar= flag, or type=file are not aliased here. + # 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"]) + typing = re.findall("bool|str|\[\]|const|false|true", opt["type"]) naming = re.findall("\[\]", opt["name"]) name = re.findall("(?