Check-in [acaea4439d]
Overview
Comment: | Implement plugin meta data extraction in config.plugin_meta() instead of channels.__init__ |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
acaea4439df7b4577156aaf10d79af18 |
User & Date: | mario on 2015-03-28 07:26:35 |
Other Links: | manifest | tags |
Context
2015-03-28
| ||
07:27 | Move bookmarks channel out of main, add proper plugin description. (Can't be disabled, is still a core plugin, and manually imported anyway.) check-in: b9dc5e172c user: mario tags: trunk | |
07:26 | Implement plugin meta data extraction in config.plugin_meta() instead of channels.__init__ check-in: acaea4439d user: mario tags: trunk | |
07:25 | Disable some debugging, move gui_startup() to mygtk collection, allow markup for mygtk.label() text. check-in: 164043075d user: mario tags: trunk | |
Changes
Modified channels/_generic.py from [e9222413a9] to [d7e715823c].
︙ | ︙ | |||
20 21 22 23 24 25 26 | # file. They derive from the ChannelPlugins class instead, which # adds the required gtk Widgets manually. # import gtk from mygtk import mygtk | | > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | # file. They derive from the ChannelPlugins class instead, which # adds the required gtk Widgets manually. # import gtk from mygtk import mygtk from config import * import ahttp as http import action import favicon import os.path import xml.sax.saxutils import re import copy import inspect # dict==object class struct(dict): def __init__(self, *xargs, **kwargs): self.__dict__ = self self.update(kwargs) [self.update(x) for x in xargs] pass # generic channel module --------------------------------------- class GenericChannel(object): # desc module = "generic" meta = {} title = "GenericChannel" homepage = "http://fossil.include-once.org/streamtuner2/" base_url = "" listformat = "audio/x-scpls" audioformat = "audio/mpeg" # fallback value config = [] has_search = False |
︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # constructor def __init__(self, parent=None): #self.streams = {} self.gtk_list = None self.gtk_cat = None # only if streamtuner2 is run in graphical mode if (parent): self.cache() self.gui(parent) pass | > > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | # constructor def __init__(self, parent=None): #self.streams = {} self.gtk_list = None self.gtk_cat = None self.meta = plugin_meta(inspect.getsourcefile(inspect.getmodule(self))) self.config = self.meta["config"] # only if streamtuner2 is run in graphical mode if (parent): self.cache() self.gui(parent) pass |
︙ | ︙ |
Modified config.py from [59ff23a453] to [cb67ede034].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # # encoding: UTF-8 # api: streamtuner2 # type: class # title: global config object # description: reads ~/.config/streamtuner/*.json files # # In the main application or module files which need access # to a global conf object, just import this module as follows: # # from config import conf # # Here conf is already an instantiation of the underlying # Config class. # import os import sys import json import gzip import platform # export symbols | > > > > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # # encoding: UTF-8 # api: streamtuner2 # .2 # 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 conf # # Here conf is already an instantiation of the underlying # Config class. # import os import sys import json import gzip import platform import re import zipfile import inspect # export symbols __all__ = ["conf", "__print__", "dbg", "plugin_meta"] #-- create a single instance of config object conf = object() |
︙ | ︙ | |||
42 43 44 45 46 47 48 | self.__dict__ = self # let's pray this won't leak memory due to recursion issues # prepare self.defaults() self.xdg() # runtime | < | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | self.__dict__ = self # let's pray this won't leak memory due to recursion issues # prepare self.defaults() self.xdg() # runtime self.share = os.path.dirname(__file__) # settings from last session last = self.load("settings") if (last): self.update(last) self.migrate() # store defaults in file |
︙ | ︙ | |||
201 202 203 204 205 206 207 208 209 210 211 212 213 214 | def find_in_dirs(self, dirs, file): for d in dirs: if os.path.exists(d+"/"+file): return d+"/"+file # wrapper for all print statements def __print__(*args): if conf.debug: print(" ".join([str(a) for a in args])) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | def find_in_dirs(self, dirs, file): for d in dirs: if os.path.exists(d+"/"+file): return d+"/"+file # Plugin meta data extraction # # Extremely crude version for Python and streamtuner2 plugin usage. # Doesn't check top-level comment coherency. # But supports plugins within python zip archives. # rx_zipfn = re.compile(r"""^(.+\.(?:zip|pyz|pyzw|pyzip)(?:\.py)?)/(\w.*)$""") rx_meta = re.compile(r"""^ {0,4}# *([\w-]+): *(.+(\n *# +(?![\w-]+:).+)*)$""", re.M) # Python comments only rx_lines = re.compile(r"""\n *# """) # strip multi-line prefixes rx_config = re.compile(r"""[\{\<](.+?)[\}\>]""") # extract only from JSOL/YAML scheme rx_fields = re.compile(r"""["']?(\w+)["']?\s*[:=]\s*["']?([^,]+)(?<!["'])""") # simple key: value entries # def plugin_meta(fn=None, frame=1, src=""): # filename of caller if not fn: fn = inspect.getfile(sys._getframe(frame)) # within zip archive? zip = rx_zipfn.match(fn) if zip and zipfile.is_zipfile(zip.group(1)): src = zipfile.ZipFile(zip.group(1), "r").read(zip.group(2)) else: src = open(fn).read(4096) # defaults meta = { "fn": fn, "id": os.path.basename(fn).replace(".py", "") } # extraction for field in rx_meta.findall(src): meta[field[0]] = rx_lines.sub("", field[1]) # unpack config: structures meta["config"] = [ dict([field for field in rx_fields.findall(entry)]) for entry in rx_config.findall(meta.get("config", "")) ] return meta # wrapper for all print statements def __print__(*args): if conf.debug: print(" ".join([str(a) for a in args])) |
︙ | ︙ | |||
227 228 229 230 231 232 233 234 | #-- actually fill global conf instance conf = ConfigDict() if conf: __print__(dbg.PROC, "ConfigDict() initialized") | < < < | 278 279 280 281 282 283 284 285 | #-- actually fill global conf instance conf = ConfigDict() if conf: __print__(dbg.PROC, "ConfigDict() initialized") |