|
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
| def get_data(filename, decode=False, gzip=False, file_base=None):
"""
Fetches file content from install path or from within PYZ
archive. This is just an alias and convenience wrapper for
pkgutil.get_data().
Utilizes the module_base / plugin_base as top-level reference.
:arg str fn: filename in pyz or bundle
:arg bool decode: text file decoding utf-8
:arg bool gz: automatic gzdecode
:arg str file_base: alternative base module reference
"""
try:
data = pkgutil.get_data(file_base or module_base, filename)
if gzip:
data = gzip_decode(data)
if decode:
return data.decode("utf-8", errors='ignore')
return str(data)
except:
# log_ERR("get_data() didn't find:", fn, "in", file_base)
pass
# Plugin name lookup
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def module_list(extra_paths=None):
"""
Search through ./plugins/ (and other configured plugin_base
names → paths) and get module basenames.
:arg list extra_paths: in addition to plugin_base list
"""
# Convert plugin_base package names into paths for iter_modules
paths = []
for module_or_path in plugin_base:
if sys.modules.get(module_or_path):
paths += sys.modules[module_or_path].__path__
|
>
>
>
|
>
|
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
| 158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
| def get_data(filename, decode=False, gzip=False, file_base=None):
"""
Fetches file content from install path or from within PYZ
archive. This is just an alias and convenience wrapper for
pkgutil.get_data().
Utilizes the module_base / plugin_base as top-level reference.
Parameters
----------
filename : str
filename in pyz or bundle
decode : bool
text file decoding utf-8
gzip : bool
automatic gzdecode
file_base : list
alternative base module reference
Returns
-------
str : file contents
"""
try:
data = pkgutil.get_data(file_base or module_base, filename)
if gzip:
data = gzip_decode(data)
if decode:
return data.decode("utf-8", errors='ignore')
return str(data)
except:
# log_ERR("get_data() didn't find:", fn, "in", file_base)
pass
# Plugin name lookup
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def module_list(extra_paths=None):
"""
Search through ./plugins/ (and other configured plugin_base
names → paths) and get module basenames.
Parameters
----------
extra_paths : list
in addition to plugin_base list
Returns
-------
list : names of found plugins
"""
# Convert plugin_base package names into paths for iter_modules
paths = []
for module_or_path in plugin_base:
if sys.modules.get(module_or_path):
paths += sys.modules[module_or_path].__path__
|
|
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
| # Plugin => meta dict
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def all_plugin_meta():
"""
This is a trivial wrapper to assemble a complete dictionary
of available/installed plugins. It associates each plugin name
with a its meta{} fields.
"""
return {
name: plugin_meta(module=name) for name in module_list()
}
# Plugin meta data extraction
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
@renamed_arguments({"fn": "filename"})
def plugin_meta(filename=None, src=None, module=None, frame=1, **kwargs):
"""
Extract plugin meta data block from different sources:
:arg str filename: read literal files, or .pyz contents
:arg str src: from already uncovered script code
:arg str module: lookup per pkgutil, from plugin_base or top-level modules
:arg int frame: extract comment header of caller (default)
:arg list extra_base: additional search directories
:arg ist max_length: maximum size to read from files
"""
# Try via pkgutil first,
# find any plugins.* modules, or main packages
if module:
filename = module
for base in plugin_base + kwargs.get("extra_base", []):
|
>
>
>
>
>
>
>
|
>
|
>
|
>
|
>
|
>
|
>
>
>
>
| 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
| # Plugin => meta dict
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def all_plugin_meta():
"""
This is a trivial wrapper to assemble a complete dictionary
of available/installed plugins. It associates each plugin name
with a its meta{} fields.
Returns
-------
dict : names to meta data dict
"""
return {
name: plugin_meta(module=name) for name in module_list()
}
# Plugin meta data extraction
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
@renamed_arguments({"fn": "filename"})
def plugin_meta(filename=None, src=None, module=None, frame=1, **kwargs):
"""
Extract plugin meta data block from different sources:
Parameters
----------
filename : str
read literal files, or .pyz contents
src : str
from already uncovered script code
module : str
lookup per pkgutil, from plugin_base or top-level modules
frame : int
extract comment header of caller (default)
extra_base : list
additional search directories
max_length : list
maximum size to read from files
Returns
-------
dict : key-value pairs of comment fields, config: preparsed
"""
# Try via pkgutil first,
# find any plugins.* modules, or main packages
if module:
filename = module
for base in plugin_base + kwargs.get("extra_base", []):
|
|
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
| @renamed_arguments({"fn": "filename"})
def plugin_meta_extract(src="", filename=None, literal=False):
"""
Finds the first comment block. Splits key:value header
fields from comment. Turns everything into an dict, with
some stub fields if absent.
:arg str src: from existing source code
:arg int filename: set filename attribute
:arg bool literla: just split comment from doc
"""
# Defaults
meta = {
"id": os.path.splitext(os.path.basename(filename or ""))[0],
"fn": filename,
"api": "python",
|
>
>
>
|
>
|
>
|
| 307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
| @renamed_arguments({"fn": "filename"})
def plugin_meta_extract(src="", filename=None, literal=False):
"""
Finds the first comment block. Splits key:value header
fields from comment. Turns everything into an dict, with
some stub fields if absent.
Parameters
----------
src : str
from existing source code
filename : str
set filename attribute
literls : bool
just split comment from doc
"""
# Defaults
meta = {
"id": os.path.splitext(os.path.basename(filename or ""))[0],
"fn": filename,
"api": "python",
|
|
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
| # Unpack config: structures
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def plugin_meta_config(src):
"""
Further breaks up the meta['config'] descriptor.
Creates an array from JSON/YAML option lists.
:arg str src: unprocessed config: field
Stubs out name, value, type, description if absent.
# config:
{ name: 'var1', type: text, value: "default, ..." }
{ name=option2, type=boolean, $value=1, etc. }
"""
config = []
for entry in rx.config.findall(src):
entry = entry[0] or entry[1]
opt = {
"type": None,
|
<
<
>
>
>
>
>
>
>
>
>
| 361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
| # Unpack config: structures
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def plugin_meta_config(src):
"""
Further breaks up the meta['config'] descriptor.
Creates an array from JSON/YAML option lists.
Stubs out name, value, type, description if absent.
# config:
{ name: 'var1', type: text, value: "default, ..." }
{ name=option2, type=boolean, $value=1, etc. }
Parameters
----------
src : str
unprocessed config: field
Returns
-------
list : of option dictionaries
"""
config = []
for entry in rx.config.findall(src):
entry = entry[0] or entry[1]
opt = {
"type": None,
|
|
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
| # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def add_plugin_defaults(conf_options, conf_plugins, meta, module=""):
"""
Utility function which collect defaults from plugin meta data to
a config store. Which in the case of streamtuner2 is really just a
dictionary `conf{}` and a plugin list in `conf.plugins{}`.
:arg dict conf_options: storage for amassed options
:arg dict conf_plugins: enable status based on plugin state/priority:
:arg dict meta: input plugin meta data (invoke once per plugin)
:arg str module: module name of meta: block
"""
# Option defaults, if not yet defined
for opt in meta.get("config", []):
if "name" not in opt or "value" not in opt:
continue
_value = opt.get("value", "")
|
>
>
>
|
>
|
>
|
>
|
| 506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
| # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
def add_plugin_defaults(conf_options, conf_plugins, meta, module=""):
"""
Utility function which collect defaults from plugin meta data to
a config store. Which in the case of streamtuner2 is really just a
dictionary `conf{}` and a plugin list in `conf.plugins{}`.
Parameters
----------
conf_options : dict : input/output
storage for amassed options
conf_plugins : dict : input/output
enable status based on plugin state/priority:
meta : dict
input plugin meta data (invoke once per plugin)
module : str
basename of meta: blocks plugin file
"""
# Option defaults, if not yet defined
for opt in meta.get("config", []):
if "name" not in opt or "value" not in opt:
continue
_value = opt.get("value", "")
|
|