︙ | | |
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
+
+
+
+
+
+
|
#
# Using a plugin_state config dictionary in most cases can just list
# module basenames, if there's only one namespace to manage. (Plugin
# names unique across project.)
"""
Plugin meta extraction and module lookup
* Main function `plugin_meta(filename=…)` unpacks
[meta fields](https://fossil.include-once.org/pluginspec/)
into dictionaries.
* Other utility code is about module location, but requires
some initialization.
![#](https://fossil.include-once.org/pluginspec/logo)
"""
import sys
import os
|
︙ | | |
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
-
+
+
|
def gzip_decode(bytestr):
""" haphazard workaround """
return zlib.decompress(bytestr, 16 + zlib.MAX_WBITS)
import zipfile
import argparse
__all__ = [
"get_data", "module_list", "plugin_meta", "add_plugin_defaults"
"plugin_meta", "get_data", "module_list", "add_plugin_defaults",
"PluginMeta", "all_plugin_meta",
]
# Injectables
# ‾‾‾‾‾‾‾‾‾‾‾
""" injectable callback function for logging """
log_ERR = lambda *x: None
|
︙ | | |
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
|
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
|
-
+
-
+
-
+
-
+
-
+
-
+
-
+
|
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
Read literal files, or .pyz contents.
src : str
from already uncovered script code
From already uncovered script code.
module : str
lookup per pkgutil, from plugin_base or top-level modules
Lookup per pkgutil, from plugin_base or top-level modules.
frame : int
extract comment header of caller (default)
Extract comment header of caller (default).
extra_base : list
additional search directories
Additional search directories.
max_length : list
maximum size to read from files
Maximum size to read from files.
Returns
-------
dict : key-value pairs of comment fields, config: preparsed
dict : Extracted comment fields, with 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", []):
|
︙ | | |
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
-
+
|
# Comment and field extraction logic
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
@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.
some stub fields if absent. Dashes substituted for underscores.
Parameters
----------
src : str
from existing source code
filename : str
set filename attribute
|
︙ | | |
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|
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
388
389
390
391
392
393
|
-
+
+
-
+
+
+
+
-
+
|
# Split comment block
if src.find("\n\n") > 0:
src, meta["doc"] = src.split("\n\n", 1)
# Turn key:value lines into dictionary
for field in rx.keyval.findall(src):
meta[field[0].replace("-", "_")] = field[1].strip()
meta[field[0].replace("-", "_").lower()] = field[1].strip()
meta["config"] = plugin_meta_config(meta.get("config") or "")
return PluginMeta(meta)
# Dict wrapper
# ‾‾‾‾‾‾‾‾‾‾‾‾
class PluginMeta(dict):
"""
""" Plugin meta data, convenience dict with property access """
Plugin meta data, as dictionary with alternative .property access.
Returned for each `plugin_meta()` result, and config: options.
Non-existent .fieldnames just resolve to `""`.
"""
def __getattr__(self, key):
""" Return [key] for .property access, else None """
return self.get(key)
return self.get(key, "")
def __hasattr__(self, key):
""" Return [key] for .property access, else None """
return key in self
# Unpack config: structures
|
︙ | | |