Overview
Comment:doc updates, minor test changes (reset/tearDown)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d8c4b46a3625dba8817f8faa93c75f176006bc9795a8c301b26ff71a6def0b12
User & Date: mario on 2022-10-30 09:13:00
Other Links: manifest | tags
Context
2022-10-30
15:03
use table markup for api docs check-in: cd360e316f user: mario tags: trunk
09:13
doc updates, minor test changes (reset/tearDown) check-in: d8c4b46a36 user: mario tags: trunk
09:11
config samples in table check-in: 675e0155fd user: mario tags: trunk
Changes

Modified README.md from [4aec538275] to [22794d9a4b].

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


# API

Lookup configuration is currently just done through injection:

    plugin_base = [__package__, "myapp.plugins", "/usr/share/app/extensions"]
    module_base = "pluginconf"  # or any top-level app module

Which declares module and plugin basenames, which get used for lookups by
just module= names in e.g. `module_list()`. (Works for literal setups
and within PYZ bundles).   
This is unnecessary for plain `plugin_meta(fn=)` extraction.

#### [plugin_meta](https://fossil.include-once.org/pluginspec/doc/trunk/html/index.html)( module= | filename= | src= | frame= )







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


# API

Lookup configuration is currently just done through injection:

    plugin_base = [__package__, "myapp.plugins", "/usr/share/app/extensions"]
    data_base = "pluginconf"  # or any top-level app module

Which declares module and plugin basenames, which get used for lookups by
just module= names in e.g. `module_list()`. (Works for literal setups
and within PYZ bundles).   
This is unnecessary for plain `plugin_meta(fn=)` extraction.

#### [plugin_meta](https://fossil.include-once.org/pluginspec/doc/trunk/html/index.html)( module= | filename= | src= | frame= )
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#### add_plugin_defaults()

Populates your config_options{} and plugin_states{} list. Can be a classic dict,
or one of the hundreds of config parser/managers. You might want to combine
config options and plugin states in a single dict even:

    import pluginconf
    pluginconf.module_base = __name__
    pluginconf.plugin_base = [__package__]

    conf = {
        "defaults": "123",
	"plugins": {}       # ← stores the activation states
    }








|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#### add_plugin_defaults()

Populates your config_options{} and plugin_states{} list. Can be a classic dict,
or one of the hundreds of config parser/managers. You might want to combine
config options and plugin states in a single dict even:

    import pluginconf
    pluginconf.data_base = __name__
    pluginconf.plugin_base = [__package__]

    conf = {
        "defaults": "123",
	"plugins": {}       # ← stores the activation states
    }

183
184
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199

It can be invoked via `flit-pluginconf build` /  `python -m pluginconf.flit build`
or even `python -m build`. Field mapping isn't very robust yet, and mercilessly
flaunts the `dynamic=` directive.



## other modules

 * `pluginconf.depends` provides `Check` for .valid() and .depends() probing

 * argparse_map() might also end up in a separate module.


#### Caveats

 * It’s mostly just an excerpt from streamtuner2.
 * Might need customization prior use.







|


>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

It can be invoked via `flit-pluginconf build` /  `python -m pluginconf.flit build`
or even `python -m build`. Field mapping isn't very robust yet, and mercilessly
flaunts the `dynamic=` directive.



# other modules

 * `pluginconf.depends` provides `Check` for .valid() and .depends() probing
 * `pluginconf.bind` is a simpler interface and basic plugin loader
 * argparse_map() might also end up in a separate module.


#### Caveats

 * It’s mostly just an excerpt from streamtuner2.
 * Might need customization prior use.

Added html/bind.html version [f4a4553477].































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>pluginconf.bind API documentation</title>
<meta name="description" content="Basic plugin loader implementation for flat namespaces. Ties together
pluginconf lookups and config management for plugin loading in apps.
It&#39;s rather …" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>pluginconf.bind</code></h1>
</header>
<section id="section-intro">
<p>Basic plugin loader implementation for flat namespaces. Ties together
pluginconf lookups and config management for plugin loading in apps.
It's rather basic, and subject to change. Does impose a config dict
format, but no storage still.</p>
<h3 id="usage-example">Usage example</h3>
<pre><code># designate a plugins/*.py package as plugin_base
import plugins
import pluginconf.bind
pluginconf.bind.base(plugins)

# preset core app settings / load from json, add plugin options
conf = {
    "plugins": {
    }
}
pluginconf.bind.defaults(conf)

# load conf-enabled plugins, and register modules somehow
for mod in pluginconf.bind.load_enabled(conf):
    mod.init()
</code></pre>
<h3 id="find-by-type">Find by type</h3>
<pre><code>for name, pmd in pluginconf.bind.find(type="effect").items():
    mod = pluginconf.bind.load(name)
    if pmd.category == "menu":
        main_win.add_menu(mod.menu)
</code></pre>
<p>Note that this uses meta data extraction, so should best be confined
for app setup/initialization, not used recurringly. The config state
usage is the preferred method. (Only requires property loading
once, for installation or with <code><a title="pluginconf.gui.window" href="gui.html#pluginconf.gui.window">window()</a></code> usage.)</p>
<hr>
<p>Method interactions: 🚐 = import, 🧩 = meta, 🧾 = config, 🛠
= setup</p>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pluginconf.bind.base"><code class="name flex">
<span>def <span class="ident">base</span></span>(<span>module, path=None)</span>
</code></dt>
<dd>
<div class="desc"><p>Register module as package/plugin_base. Or expand its search path 🛠 .</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>module</code></strong> :&ensp;<code>module/str</code></dt>
<dd>The package basename to later load plugins from (must be a package,
like <code>plugins/__init__.py</code>, or be tied to a path= or zip). Ideally
this module was already imported in main. But parameter may be a string.</dd>
<dt><strong><code>path</code></strong> :&ensp;<code>str</code></dt>
<dd>Add a directory or pyz/zip bundle to registered plugin_base. Could
be invoked multiple times =./contrib/, =/usr/share/app/extenstions/,
=~/.config/app/userplug/ (same as declaring the <code>__path__</code> in the
base <code>package/__init__.py</code>.)</dd>
</dl></div>
</dd>
<dt id="pluginconf.bind.defaults"><code class="name flex">
<span>def <span class="ident">defaults</span></span>(<span>conf)</span>
</code></dt>
<dd>
<div class="desc"><p>Traverse installed plugins and expand config dict with presets 🧩 🧾</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>conf</code></strong> :&ensp;<code>dict 🔁</code></dt>
<dd>Expands the top-level config dict with preset values from any plugins.</dd>
</dl></div>
</dd>
<dt id="pluginconf.bind.find"><code class="name flex">
<span>def <span class="ident">find</span></span>(<span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Find plugins by e.g. type= or category= 🧩</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>type</code></strong> :&ensp;<code>str</code></dt>
<dd>Usually you'd search on a designated plugin categorization, like type=
and api=, or slot=, or class= or whatever is most consistent. Multiple
attributes can be filtered on. (Version/title probably not useful here.)</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>dict</code></strong> :&ensp;<code>basename → PluginMeta dict</code></dt>
<dd>&nbsp;</dd>
</dl></div>
</dd>
<dt id="pluginconf.bind.load"><code class="name flex">
<span>def <span class="ident">load</span></span>(<span>name)</span>
</code></dt>
<dd>
<div class="desc"><p>Import individual plugin from any of the base paths 🚐</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>name</code></strong> :&ensp;<code>str</code></dt>
<dd>Plugin name in any of the registered plugin_base´s. (The whole
namespace is assumed to be flat, and identifiers to be unique.)</dd>
</dl></div>
</dd>
<dt id="pluginconf.bind.load_enabled"><code class="name flex">
<span>def <span class="ident">load_enabled</span></span>(<span>conf)</span>
</code></dt>
<dd>
<div class="desc"><p>Import modules that are enabled in conf[plugins]={name:True,…} 🧾 🚐</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>conf</code></strong> :&ensp;<code>dict</code></dt>
<dd>Simple options-value dictionary, but with one conf["plugins"] = {} subdict,
which holds plugin activation states. The config dict doesn't have to match
the available plugin options (defaults can be added), but should focus on
essential presets. Differentiation only might become relevant for storage.</dd>
</dl></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pluginconf.bind.isolated"><code class="flex name class">
<span>class <span class="ident">isolated</span></span>
<span>(</span><span>package)</span>
</code></dt>
<dd>
<div class="desc"><p>Context manager for isolated plugin structures.
🛠
This is a shallow alternative to pluginbase and library-level plugins.
Temporarily swaps global settings, thus maps most static functions.</p>
<pre><code>with pluginconf.bind.isolated("libplugins") as bound:
    bound.modules2.init()
    print(
        bound.find(api="library")
    )
</code></pre></div>
<h3>Static methods</h3>
<dl>
<dt id="pluginconf.bind.isolated.defaults"><code class="name flex">
<span>def <span class="ident">defaults</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p><em>return</em> defaults for isolated plugin structure 🧩 🧾</p></div>
</dd>
<dt id="pluginconf.bind.isolated.find"><code class="name flex">
<span>def <span class="ident">find</span></span>(<span>**kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>find by meta attributes 🧩</p></div>
</dd>
<dt id="pluginconf.bind.isolated.load"><code class="name flex">
<span>def <span class="ident">load</span></span>(<span>name)</span>
</code></dt>
<dd>
<div class="desc"><p>load module from wrapped package 🚐</p></div>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="pluginconf.bind.isolated.get_data"><code class="name flex">
<span>def <span class="ident">get_data</span></span>(<span>self, *args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>get file relative to encapsulated plugins 🚐</p></div>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul>
<li><a href="#usage-example">Usage example</a></li>
<li><a href="#find-by-type">Find by type</a></li>
</ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="pluginconf" href="index.html">pluginconf</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="pluginconf.bind.base" href="#pluginconf.bind.base">base</a></code></li>
<li><code><a title="pluginconf.bind.defaults" href="#pluginconf.bind.defaults">defaults</a></code></li>
<li><code><a title="pluginconf.bind.find" href="#pluginconf.bind.find">find</a></code></li>
<li><code><a title="pluginconf.bind.load" href="#pluginconf.bind.load">load</a></code></li>
<li><code><a title="pluginconf.bind.load_enabled" href="#pluginconf.bind.load_enabled">load_enabled</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="pluginconf.bind.isolated" href="#pluginconf.bind.isolated">isolated</a></code></h4>
<ul class="">
<li><code><a title="pluginconf.bind.isolated.defaults" href="#pluginconf.bind.isolated.defaults">defaults</a></code></li>
<li><code><a title="pluginconf.bind.isolated.find" href="#pluginconf.bind.isolated.find">find</a></code></li>
<li><code><a title="pluginconf.bind.isolated.get_data" href="#pluginconf.bind.isolated.get_data">get_data</a></code></li>
<li><code><a title="pluginconf.bind.isolated.load" href="#pluginconf.bind.isolated.load">load</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

Modified html/flit.html from [29c041b882] to [60463df35e].

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
</header>
<section id="section-intro">
<p>monkeypatches flit to use pluginconf sources for packaging with a
<code>pyproject.toml</code> like:</p>
<table>
<tr><th>pyproject.toml</th>
<th>foobar/__init__.py</th></tr>
<tr><td><pre>
[build-system]
requires = ["pluginconf", "flit]
build-backend = "pluginconf.flit"

[project]
name = "foobar"
dynamic = ["*"]
</pre></td>
<td><pre>
# title: foobar
# description: package summary
# version: 2.5.0
# depends: python:requests >= 2.25
# license: MITL
# classifiers: backend, text
# url: http;//example.org
</pre></td></tr>
</table>
<p>Can be invoked per <code>flit-pluginconf build</code> or <code>python -m build</code>.</p>
<p><img src="/pluginspec/doc/tip/html/flit.gif" alt="flit - can't believe it's not setup.py!!"></p>
</section>
<section>
</section>
<section>







|







|
|







|







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
</header>
<section id="section-intro">
<p>monkeypatches flit to use pluginconf sources for packaging with a
<code>pyproject.toml</code> like:</p>
<table>
<tr><th>pyproject.toml</th>
<th>foobar/__init__.py</th></tr>
<tr><td><code><pre>
[build-system]
requires = ["pluginconf", "flit]
build-backend = "pluginconf.flit"

[project]
name = "foobar"
dynamic = ["*"]
</pre></code></td>
<td><code><pre>
# title: foobar
# description: package summary
# version: 2.5.0
# depends: python:requests >= 2.25
# license: MITL
# classifiers: backend, text
# url: http;//example.org
</pre></code></td></tr>
</table>
<p>Can be invoked per <code>flit-pluginconf build</code> or <code>python -m build</code>.</p>
<p><img src="/pluginspec/doc/tip/html/flit.gif" alt="flit - can't believe it's not setup.py!!"></p>
</section>
<section>
</section>
<section>

Modified html/index.html from [381d830594] to [9345b17570].

18
19
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
60
61
62
63
64
<body>
<main>
<article id="content">
<header>
<h1 class="title">Package <code>pluginconf</code></h1>
</header>
<section id="section-intro">
<p>Plugin meta extraction and module lookup</p>
<ul>
<li>Main function <code>plugin_meta(filename=…)</code> unpacks
<a href="https://fossil.include-once.org/pluginspec/">meta fields</a>



into dictionaries.</li>
<li>Other utility code is about module location, but requires
some initialization.</li>
</ul>


<p><img alt="#" src="https://fossil.include-once.org/pluginspec/logo"></p>

</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>






<dt><code class="name"><a title="pluginconf.depends" href="depends.html">pluginconf.depends</a></code></dt>
<dd>
<div class="desc"><p>Dependency validation and consistency checker for updates</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.flit" href="flit.html">pluginconf.flit</a></code></dt>
<dd>
<div class="desc"><p>monkeypatches flit to use pluginconf sources for packaging with a
<code>pyproject.toml</code> like: …</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.gui" href="gui.html">pluginconf.gui</a></code></dt>
<dd>
<div class="desc"><p>PySimpleGUI window to populate config dict via plugin options …</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.setup" href="setup.html">pluginconf.setup</a></code></dt>
<dd>
<div class="desc"><p>Simulates setuptools.setup()</p></div>
</dd>
</dl>
</section>
<section>


















</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pluginconf.add_plugin_defaults"><code class="name flex">
<span>def <span class="ident">add_plugin_defaults</span></span>(<span>conf_options, conf_plugins, meta, module='')</span>
</code></dt>







|
|
<
|
>
>
>
|
|
<
<
>
>
|
>




>
>
>
>
>
>















|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







18
19
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<body>
<main>
<article id="content">
<header>
<h1 class="title">Package <code>pluginconf</code></h1>
</header>
<section id="section-intro">
<p>Plugin meta extraction and module lookup.</p>
<table><tr><td>

<img src="https://fossil.include-once.org/pluginspec/logo">
</td>
<td>
<li> Main function <a href="#pluginconf.plugin_meta">plugin_meta()</a> unpacks meta fields
into dictionaries.
<li> Other utility code is about module listing, relative to


<a href="#pluginconf.plugin_base">plugin_base</a> anchors.
<li> <a href="https://pypi.org/project/pluginconf/">//pypi.org/project/pluginconf/</a>
<li> <a href="https://fossil.include-once.org/pluginspec/">//fossil.include-once.org/pluginspec/</a>
</td></tr></table>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="pluginconf.bind" href="bind.html">pluginconf.bind</a></code></dt>
<dd>
<div class="desc"><p>Basic plugin loader implementation for flat namespaces. Ties together
pluginconf lookups and config management for plugin loading in apps.
It's rather …</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.depends" href="depends.html">pluginconf.depends</a></code></dt>
<dd>
<div class="desc"><p>Dependency validation and consistency checker for updates</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.flit" href="flit.html">pluginconf.flit</a></code></dt>
<dd>
<div class="desc"><p>monkeypatches flit to use pluginconf sources for packaging with a
<code>pyproject.toml</code> like: …</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.gui" href="gui.html">pluginconf.gui</a></code></dt>
<dd>
<div class="desc"><p>PySimpleGUI window to populate config dict via plugin options …</p></div>
</dd>
<dt><code class="name"><a title="pluginconf.setup" href="setup.html">pluginconf.setup</a></code></dt>
<dd>
<div class="desc"><p>Expands setuptools.setup() with automatic package description lookup</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-variables">Global variables</h2>
<dl>
<dt id="pluginconf.config_opt_type_map"><code class="name">var <span class="ident">config_opt_type_map</span></code></dt>
<dd>
<div class="desc"><p>normalize config type: names to <code>str</code>, <code>text</code>, <code>bool</code>, <code>int</code>, <code>select</code>, <code>dict</code></p></div>
</dd>
<dt id="pluginconf.data_root"><code class="name">var <span class="ident">data_root</span></code></dt>
<dd>
<div class="desc"><p>File lookup relation for get_data(), should name a top-level package.
(Equivalent to <code>PluginBase(package=…)</code>)</p></div>
</dd>
<dt id="pluginconf.plugin_base"><code class="name">var <span class="ident">plugin_base</span></code></dt>
<dd>
<div class="desc"><p>Package/module names (or directories) for module_list() and plugin_meta()
lookups. Associated paths (<code>__path__</code>) will be scanned for module/plugin
basenames. (Similar to <code>PluginBase(searchpath=…)</code>)</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pluginconf.add_plugin_defaults"><code class="name flex">
<span>def <span class="ident">add_plugin_defaults</span></span>(<span>conf_options, conf_plugins, meta, module='')</span>
</code></dt>
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>dict</code></strong> :&ensp;<code>names to meta data dict</code></dt>
<dd>&nbsp;</dd>
</dl></div>
</dd>
<dt id="pluginconf.get_data"><code class="name flex">
<span>def <span class="ident">get_data</span></span>(<span>filename, decode=False, gzip=False, file_base=None)</span>
</code></dt>
<dd>
<div class="desc"><p>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.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>filename</code></strong> :&ensp;<code> str</code></dt>
<dd>filename in pyz or bundle</dd>
<dt><strong><code>decode</code></strong> :&ensp;<code>bool</code></dt>
<dd>text file decoding utf-8</dd>
<dt><strong><code>gzip</code></strong> :&ensp;<code>bool</code></dt>
<dd>automatic gzdecode</dd>
<dt><strong><code>file_base</code></strong> :&ensp;<code>list</code></dt>
<dd>alternative base module reference</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>str</code></strong> :&ensp;<code>file contents</code></dt>
<dd>&nbsp;</dd>
</dl></div>
</dd>







|





|








|
|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>dict</code></strong> :&ensp;<code>names to meta data dict</code></dt>
<dd>&nbsp;</dd>
</dl></div>
</dd>
<dt id="pluginconf.get_data"><code class="name flex">
<span>def <span class="ident">get_data</span></span>(<span>filename, decode=False, gzip=False, file_root=None)</span>
</code></dt>
<dd>
<div class="desc"><p>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 data_root as top-level reference.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>filename</code></strong> :&ensp;<code> str</code></dt>
<dd>filename in pyz or bundle</dd>
<dt><strong><code>decode</code></strong> :&ensp;<code>bool</code></dt>
<dd>text file decoding utf-8</dd>
<dt><strong><code>gzip</code></strong> :&ensp;<code>bool</code></dt>
<dd>automatic gzdecode</dd>
<dt><strong><code>file_root</code></strong> :&ensp;<code>list</code></dt>
<dd>alternative base module (application or pyz root)</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>str</code></strong> :&ensp;<code>file contents</code></dt>
<dd>&nbsp;</dd>
</dl></div>
</dd>
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
214
215
216
217
218
219
220
<dd>&nbsp;</dd>
</dl></div>
</dd>
<dt id="pluginconf.plugin_meta"><code class="name flex">
<span>def <span class="ident">plugin_meta</span></span>(<span>filename=None, src=None, module=None, frame=1, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Extract plugin meta data block from different sources:</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>filename</code></strong> :&ensp;<code>str</code></dt>
<dd>Read literal files, or .pyz contents.</dd>
<dt><strong><code>src</code></strong> :&ensp;<code>str</code></dt>
<dd>From already uncovered script code.</dd>
<dt><strong><code>module</code></strong> :&ensp;<code>str</code></dt>
<dd>Lookup per pkgutil, from plugin_base or top-level modules.</dd>
<dt><strong><code>frame</code></strong> :&ensp;<code>int</code></dt>
<dd>Extract comment header of caller (default).</dd>
<dt><strong><code>extra_base</code></strong> :&ensp;<code>list</code></dt>
<dd>Additional search directories.</dd>
<dt><strong><code>max_length</code></strong> :&ensp;<code>list</code></dt>
<dd>Maximum size to read from files.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>dict</code></strong> :&ensp;<code>Extracted comment fields, with config: preparsed</code></dt>
<dd>&nbsp;</dd>
</dl></div>



</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>











<dt id="pluginconf.PluginMeta"><code class="flex name class">
<span>class <span class="ident">PluginMeta</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Plugin meta data, as dictionary with alternative .property access.
Returned for each <code><a title="pluginconf.plugin_meta" href="#pluginconf.plugin_meta">plugin_meta()</a></code> result, and config: options.
Non-existent .fieldnames just resolve to <code>""</code>.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.dict</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>

<li><code><a title="pluginconf.depends" href="depends.html">pluginconf.depends</a></code></li>
<li><code><a title="pluginconf.flit" href="flit.html">pluginconf.flit</a></code></li>
<li><code><a title="pluginconf.gui" href="gui.html">pluginconf.gui</a></code></li>
<li><code><a title="pluginconf.setup" href="setup.html">pluginconf.setup</a></code></li>
</ul>







</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="pluginconf.add_plugin_defaults" href="#pluginconf.add_plugin_defaults">add_plugin_defaults</a></code></li>
<li><code><a title="pluginconf.all_plugin_meta" href="#pluginconf.all_plugin_meta">all_plugin_meta</a></code></li>
<li><code><a title="pluginconf.get_data" href="#pluginconf.get_data">get_data</a></code></li>
<li><code><a title="pluginconf.module_list" href="#pluginconf.module_list">module_list</a></code></li>
<li><code><a title="pluginconf.plugin_meta" href="#pluginconf.plugin_meta">plugin_meta</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>



<li>
<h4><code><a title="pluginconf.PluginMeta" href="#pluginconf.PluginMeta">PluginMeta</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>







|













|





|
>
>
>






>
>
>
>
>
>
>
>
>
>
>





|
|
|
















>





>
>
>
>
>
>
>












>
>
>













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
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
<dd>&nbsp;</dd>
</dl></div>
</dd>
<dt id="pluginconf.plugin_meta"><code class="name flex">
<span>def <span class="ident">plugin_meta</span></span>(<span>filename=None, src=None, module=None, frame=1, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Extract plugin meta data block from specified source.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>filename</code></strong> :&ensp;<code>str</code></dt>
<dd>Read literal files, or .pyz contents.</dd>
<dt><strong><code>src</code></strong> :&ensp;<code>str</code></dt>
<dd>From already uncovered script code.</dd>
<dt><strong><code>module</code></strong> :&ensp;<code>str</code></dt>
<dd>Lookup per pkgutil, from plugin_base or top-level modules.</dd>
<dt><strong><code>frame</code></strong> :&ensp;<code>int</code></dt>
<dd>Extract comment header of caller (default).</dd>
<dt><strong><code>extra_base</code></strong> :&ensp;<code>list</code></dt>
<dd>Additional search directories.</dd>
<dt><strong><code>max_length</code></strong> :&ensp;<code>list</code></dt>
<dd>Maximum size to read from files (6K default).</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><strong><code>dict</code></strong> :&ensp;<code>Extracted comment fields, with config: preparsed</code></dt>
<dd>&nbsp;</dd>
</dl>
<p>The result dictionary has fields accessible as e.g. <code>pmd["title"]</code>
or <code>pmd.version</code>. The documentation block after all fields: is called
["doc"]<code>. And </code>pmd.config` already parsed as a list of dictionaries.</p></div>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pluginconf.OptionList"><code class="flex name class">
<span>class <span class="ident">OptionList</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>List of <code>config:</code> options, with alernative <code>.name</code> access (lookup by name= from option entry).</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.list</li>
</ul>
</dd>
<dt id="pluginconf.PluginMeta"><code class="flex name class">
<span>class <span class="ident">PluginMeta</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Plugin meta data as dictionary<code>{}</code>, or alternatively <code>.property</code> access.
Returned for each <code><a title="pluginconf.plugin_meta" href="#pluginconf.plugin_meta">plugin_meta()</a></code> result, and individual <code>config:</code> options.
Absent <code>.field</code> access resolves to <code>""</code>.</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.dict</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="pluginconf.bind" href="bind.html">pluginconf.bind</a></code></li>
<li><code><a title="pluginconf.depends" href="depends.html">pluginconf.depends</a></code></li>
<li><code><a title="pluginconf.flit" href="flit.html">pluginconf.flit</a></code></li>
<li><code><a title="pluginconf.gui" href="gui.html">pluginconf.gui</a></code></li>
<li><code><a title="pluginconf.setup" href="setup.html">pluginconf.setup</a></code></li>
</ul>
</li>
<li><h3><a href="#header-variables">Global variables</a></h3>
<ul class="">
<li><code><a title="pluginconf.config_opt_type_map" href="#pluginconf.config_opt_type_map">config_opt_type_map</a></code></li>
<li><code><a title="pluginconf.data_root" href="#pluginconf.data_root">data_root</a></code></li>
<li><code><a title="pluginconf.plugin_base" href="#pluginconf.plugin_base">plugin_base</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="pluginconf.add_plugin_defaults" href="#pluginconf.add_plugin_defaults">add_plugin_defaults</a></code></li>
<li><code><a title="pluginconf.all_plugin_meta" href="#pluginconf.all_plugin_meta">all_plugin_meta</a></code></li>
<li><code><a title="pluginconf.get_data" href="#pluginconf.get_data">get_data</a></code></li>
<li><code><a title="pluginconf.module_list" href="#pluginconf.module_list">module_list</a></code></li>
<li><code><a title="pluginconf.plugin_meta" href="#pluginconf.plugin_meta">plugin_meta</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="pluginconf.OptionList" href="#pluginconf.OptionList">OptionList</a></code></h4>
</li>
<li>
<h4><code><a title="pluginconf.PluginMeta" href="#pluginconf.PluginMeta">PluginMeta</a></code></h4>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>

Modified html/setup.html from [70f7b7c594] to [659fad6a18].

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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>pluginconf.setup API documentation</title>
<meta name="description" content="Simulates setuptools.setup()" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>pluginconf.setup</code></h1>
</header>
<section id="section-intro">
<p>Simulates setuptools.setup()</p>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>







|
















|







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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>pluginconf.setup API documentation</title>
<meta name="description" content="Expands setuptools.setup() with automatic package description lookup" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>pluginconf.setup</code></h1>
</header>
<section id="section-intro">
<p>Expands setuptools.setup() with automatic package description lookup</p>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pluginconf.setup.MetaUtils"><code class="flex name class">
<span>class <span class="ident">MetaUtils</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>convenience access to PMD fields</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.dict</li>
</ul>
<h3>Static methods</h3>
<dl>
<dt id="pluginconf.setup.MetaUtils.datafiles_man"><code class="name flex">







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pluginconf.setup.MetaUtils"><code class="flex name class">
<span>class <span class="ident">MetaUtils</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>Convenience access to PMD fields and conversion functions</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>builtins.dict</li>
</ul>
<h3>Static methods</h3>
<dl>
<dt id="pluginconf.setup.MetaUtils.datafiles_man"><code class="name flex">

Modified pluginconf/gui.py from [309455414c] to [fd35fa0517].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Very crude, and not as many widgets as the Gtk/St2 implementation.
# Supports type: str, bool, select, int, dict, text config: options.
#

"""
PySimpleGUI window to populate config dict via plugin options

![](http://fossil.include-once.org/streamtuner2/raw/st2-plugins.png?name=946c0e32c868a22facd7498250451723a50ab00a)
"""


#import os
import re
#import json
import glob







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Very crude, and not as many widgets as the Gtk/St2 implementation.
# Supports type: str, bool, select, int, dict, text config: options.
#

"""
PySimpleGUI window to populate config dict via plugin options

![config window](/pluginspec/doc/tip/html/config.png)
"""


#import os
import re
#import json
import glob

Modified pluginconf/setup.py from [2c993b00fe] to [a5d9b67dec].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#
# A README.* will be read if present, else PMD comment used.
# Classifiers and license matching is very crude, just for
# the most common cases. Type:, Category: and Classifiers:
# or Keywords: are also scanned for trove classifers.
#

""" Simulates setuptools.setup() """


import os
import re
import glob
import pprint
import pluginconf







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#
# A README.* will be read if present, else PMD comment used.
# Classifiers and license matching is very crude, just for
# the most common cases. Type:, Category: and Classifiers:
# or Keywords: are also scanned for trove classifers.
#

""" Expands setuptools.setup() with automatic package description lookup """


import os
import re
import glob
import pprint
import pluginconf
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    return {
        "long_description": "",
        "long_description_content_type": "text/plain",
    }


class MetaUtils(dict):
    """ convenience access to PMD fields """

    def __getattr__(self, name):
        """ dict into properties """
        return self.get(name, "")

    def plugin_doc(self):
        """ use comment block """







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    return {
        "long_description": "",
        "long_description_content_type": "text/plain",
    }


class MetaUtils(dict):
    """ Convenience access to PMD fields and conversion functions """

    def __getattr__(self, name):
        """ dict into properties """
        return self.get(name, "")

    def plugin_doc(self):
        """ use comment block """

Modified test/pyz.py from [c33e5bdbba] to [6bf0e6292d].

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
39
40
41
42

43
44
45
import pluginconf

sys.path.insert(0, f"{os.path.dirname(__file__)}/.pyz.pyz")
#os.chdir(os.path.dirname(__file__))

@pytest.fixture
def init():
    print(pluginconf.module_base)
    pluginconf.module_base = ["config"]    # must be one of the .pyz-contained modules (should be a dir/submodule for real uses)
    pluginconf.plugin_base = ["inner"]     # relative, must declare __path__, can't be __main__.py

@pytest.fixture
def pmd():
    return pluginconf.plugin_meta(module="inner")

def importy(init):
    import inner as pyz_inner
    #print(pyz_inner.__file__)

def module_list(init):
    assert set(pluginconf.module_list()) & {'__main__', 'config', 'inner'}

def inner_props(pmd):
    assert pmd["type"] == "pyz"
    assert pmd["category"] == "complex"
    assert pmd["title"] == "pyz module"
    assert pmd["config"][0]["name"] == "relation"
    assert pmd["state"] == "alpha"

#def tearDown():

#    pass#pluginconf.plugin_base = [".", "test", os.path.dirname(__file__), "."]
#    #pluginconf.module_base = "all_plugin_meta"
#    sys.path.pop(0)







|
|
|



















|
>



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
39
40
41
42
43
44
45
46
import pluginconf

sys.path.insert(0, f"{os.path.dirname(__file__)}/.pyz.pyz")
#os.chdir(os.path.dirname(__file__))

@pytest.fixture
def init():
    print(pluginconf.plugin_base)
    pluginconf.data_root = ["config"]    # must be one of the .pyz-contained modules (should be a dir/submodule for real uses)
    pluginconf.plugin_base = ["inner"]   # relative, must declare __path__, can't be __main__.py

@pytest.fixture
def pmd():
    return pluginconf.plugin_meta(module="inner")

def importy(init):
    import inner as pyz_inner
    #print(pyz_inner.__file__)

def module_list(init):
    assert set(pluginconf.module_list()) & {'__main__', 'config', 'inner'}

def inner_props(pmd):
    assert pmd["type"] == "pyz"
    assert pmd["category"] == "complex"
    assert pmd["title"] == "pyz module"
    assert pmd["config"][0]["name"] == "relation"
    assert pmd["state"] == "alpha"

def tearDown(reset):
    pass
#    pass#pluginconf.plugin_base = [".", "test", os.path.dirname(__file__), "."]
#    #pluginconf.module_base = "all_plugin_meta"
#    sys.path.pop(0)

Modified test/setup.py from [75184c3ebc] to [c141281dce].

21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36


def attributes(mocker, pmd):

    stop = mocker.patch('setuptools.setup', _record)
    pluginconf.setup.setup(
        fn="pluginconf/__init__.py",

    )
    
    assert attr["classifiers"]
    assert attr["project_urls"]
    assert attr["packages"] == ['pluginconf', 'test']
    assert attr["long_description_content_type"] == 'text/markdown'
    assert attr["license"] == 'PD'
    assert attr["keywords"] == 'config'
    assert attr["long_description"].find("meta data") > 0







>




|




21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37


def attributes(mocker, pmd):

    stop = mocker.patch('setuptools.setup', _record)
    pluginconf.setup.setup(
        fn="pluginconf/__init__.py",
        packages = ["pluginconf"],
    )
    
    assert attr["classifiers"]
    assert attr["project_urls"]
    assert attr["packages"] == ['pluginconf']
    assert attr["long_description_content_type"] == 'text/markdown'
    assert attr["license"] == 'PD'
    assert attr["keywords"] == 'config'
    assert attr["long_description"].find("meta data") > 0