Check-in [70c2e437fd]
Overview
Comment: | More complete plugin_meta() regex patterns. Now defaults to inspect.get_comments() on previous stack frame, src= or fn= only accepted as fallback. Complete default meta fields, splits doc block out, autostrips hash prefixes and indentation. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
70c2e437fd9755050b79f9bcc395e403 |
User & Date: | mario on 2015-03-29 03:06:37 |
Other Links: | manifest | tags |
Context
2015-03-29
| ||
03:08 | Use .meta[title] instead of literal property. Channel list in config_dialog completed again with disabled plugins. New tooltop for comment doc section. check-in: ead195d25c user: mario tags: trunk | |
03:06 | More complete plugin_meta() regex patterns. Now defaults to inspect.get_comments() on previous stack frame, src= or fn= only accepted as fallback. Complete default meta fields, splits doc block out, autostrips hash prefixes and indentation. check-in: 70c2e437fd user: mario tags: trunk | |
03:03 | Removed static .title and .module properties. Plugin discovery now realized through pkgutil.iter_modules(). check-in: 2b3b50b6ad user: mario tags: trunk | |
Changes
Modified config.py from [cb67ede034] to [1c74200e99].
1 2 3 | # # encoding: UTF-8 # api: streamtuner2 | < | 1 2 3 4 5 6 7 8 9 10 | # # 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: |
︙ | ︙ | |||
27 28 29 30 31 32 33 | import inspect # export symbols __all__ = ["conf", "__print__", "dbg", "plugin_meta"] | < | > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import inspect # export symbols __all__ = ["conf", "__print__", "dbg", "plugin_meta"] #-- create a stub instance of config object conf = object() #-- global configuration data --------------------------------------------- class ConfigDict(dict): # start |
︙ | ︙ | |||
177 178 179 180 181 182 183 | else: return # file not found # decode r = json.load(f) f.close() return r except Exception as e: | | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | else: return # file not found # decode r = json.load(f) f.close() return r except Exception as e: print(dbg.ERR, "JSON parsing error (in "+name+")", e) # recursive dict update def update(self, with_new_data): for key,value in with_new_data.items(): if type(value) == dict: self[key].update(value) |
︙ | ︙ | |||
208 209 210 211 212 213 214 | return d+"/"+file # Plugin meta data extraction # # Extremely crude version for Python and streamtuner2 plugin usage. | | < < < < < < < < | | | | > > | > | | | | | > > > > | > > > > > > > > > | | > | | > > > | > | > > | < < | > | | > > > > > > > > > > > > > > > > > > > | > | | > > > | < | < | 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 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 309 310 311 312 313 314 315 316 317 318 319 320 | return d+"/"+file # Plugin meta data extraction # # Extremely crude version for Python and streamtuner2 plugin usage. # Fetches module source, or reads from filename / out of zip package. def plugin_meta(fn=None, src=None, frame=1): # get source directly from caller if not src and not fn: module = inspect.getmodule(sys._getframe(frame)) fn = inspect.getsourcefile(module) src = inspect.getcomments(module) # within zip archive or dir? elif fn: 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 = { "id": re.sub("\.\w+$", "", os.path.basename(fn or "")), "fn": fn, "title": fn, "description": "no description", "config": [], "type": "module", "api": "python", "doc": "" } # extract coherent comment block, split doc section src = rx.comment.search(src) if not src: __print__(dbg.ERR, "Couldn't read source meta information", fn) return meta src = src.group(0) src = rx.hash.sub("", src).strip() if src.find("\n\n") > 0: src, meta["doc"] = src.split("\n\n", 1) # split into dict for field in rx.keyval.findall(src): meta[field[0]] = field[1].strip() meta["config"] = plugin_meta_config(meta.get("config") or "") return meta # unpack config: structures def plugin_meta_config(str): config = [] for entry in rx.config.findall(str): opt = { "type": None, "name": None, "description": "", "value": None } for field in rx.options.findall(entry): opt[field[0]] = (field[1] or field[2] or field[3] or "").strip() config.append(opt) return config # Comment extraction regexps class rx: zipfn = re.compile(r""" ^ (.+ \.(?:zip|pyz|pyzw|pyzip) # zip-wrapping extensions (?:\.py)? ) /(\w.*) $ """, re.X) comment = re.compile(r"""(^ {0,4}#.*\n)+""", re.M) hash = re.compile(r"""(^ {0,4}# *)""", re.M) keyval = re.compile(r""" ^([\w-]+):(.*$(?:\n(?![\w-]+:).+$)*) # plain key:value lines """, re.M|re.X) config = re.compile(r""" [\{\<] (.+?) [\}\>] # JSOL/YAML scheme {...} dicts """, re.X) options = re.compile(r""" ["':$]? (\w+) ["']? # key or ":key" or '$key' \s* [:=] \s* # "=" or ":" (?: " ([^"]*) " | ' ([^']*) ' # "quoted" or 'singl' values | ([^,]*) # or unquoted literals ) """, re.X) # wrapper for all print statements def __print__(*args): if "debug" in conf: print(" ".join([str(a) for a in args])) # error colorization dbg = type('obj', (object,), { "ERR": r"[31m[ERR][0m", # red ERROR "INIT": r"[31m[INIT][0m", # red INIT ERROR "PROC": r"[32m[PROC][0m", # green PROCESS "CONF": r"[33m[CONF][0m", # brown CONFIG DATA "UI": r"[34m[UI][0m", # blue USER INTERFACE BEHAVIOUR "HTTP": r"[35m[HTTP][0m", # magenta HTTP REQUEST "DATA": r"[36m[DATA][0m", # cyan DATA "INFO": r"[37m[INFO][0m", # gray INFO "STAT": r"[37m[STATE][0m", # gray CONFIG STATE }) #-- populate global conf instance conf = ConfigDict() __print__(dbg.PROC, "ConfigDict() initialized") |