Differences From Artifact [1b5dd2ab14]:

To Artifact [b93e156971]:


292
293
294
295
296
297
298
299


300
301
302
303
304
305
306


307



308
309
310
311
312
313
314
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






-
+
+







+
+
-
+
+
+







        search = plugin_base + kwargs.get("extra_base", [])
        for base, sfx in itertools.product(search, [".py", "/__init__.py"]):
            try:
                #log.debug(f"mod={base} fn={filename}.py")
                src = get_data(filename=module+sfx, decode=True, file_root=base, warn=False)
                if src:
                    break
            except (IOError, OSError, FileNotFoundError):
            except (IOError, OSError, FileNotFoundError, UnicodeDecodeError) as exc:
                log.debug("base=%s module=%s sfx=%s, exception=%s", base, module, sfx, exc)
                continue  # plugin_meta_extract() will print a notice later
        else:
            log.warning("Found no source candidate for '%s'", module)
        filename = module

    # Real filename/path
    elif filename and os.path.exists(filename):
        try:
            with open(filename, "r", encoding="utf-8") as read:
        src = open(filename).read(kwargs.get("max_length", 6144))
                src = read.read(kwargs.get("max_length", 6144))
        except UnicodeDecodeError as exc:
            log.error("read/decode error %s for %s", exc, filename)

    # Else get source directly from caller
    elif not src and not filename:
        module = inspect.getmodule(sys._getframe(frame+1)) # decorator+1
        filename = inspect.getsourcefile(module)
        src = inspect.getcomments(module)

346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377






-
+











-
+







    | src         | str     | from existing source code       |
    | filename    | str     | set filename attribute          |
    | literal     | bool    | just split comment from doc     |
    | **Returns** | dict    | fields                          |
    """

    # Defaults
    meta = {
    meta = PluginMeta({
        "id": os.path.splitext(os.path.basename(filename or ""))[0],
        "fn": filename,
        "api": "python",
        "type": "module",
        "category": None,
        "priority": None,
        "version": "0",
        "title": filename,
        "description": "no description",
        "config": [],
        "doc": ""
    }
    })

    # Extract coherent comment block
    src = src.replace("\r", "")
    if not literal:
        src = rx.header.sub("", src)
        src = rx.comment.search(src)
        if not src:
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399






-
+







        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("-", "_").lower()] = field[1].strip()
    meta["config"] = plugin_meta_config(meta.get("config") or "")

    return PluginMeta(meta)
    return meta


# Dict/list wrappers
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
class PluginMeta(dict):
    """
    Plugin meta data as dictionary`{}`, or alternatively `.property` access.