Skip to content

Commit

Permalink
ENH: plugin directory supports multiple interfaces (#206)
Browse files Browse the repository at this point in the history
The plugin directory now displays CLI and Artifact API help text for actions instead of a custom table of inputs, parameters, and outputs (this table was generally confusing to users).

Thanks @thermokarst for having the idea of using the help text that's already being generated for the CLI and Artifact API! The code is much simpler now too :)

Also, instead of using an action's underscored name (`Action.id`), the action's CLI name (dashed) is used in URLs and content.
  • Loading branch information
jairideout authored and thermokarst committed Sep 27, 2017
1 parent 255d298 commit d08a5a7
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 85 deletions.
58 changes: 31 additions & 27 deletions source/sphinx_extensions/plugin_directory/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@
import os
import os.path
import shutil
import subprocess
import textwrap

import jinja2
import qiime2.sdk


def generate_rst(app):
app.info("Generating QIIME 2 plugin directory... (this may take awhile)")

# Refresh the CLI cache just in case it is out of date with what's
# installed (this should only affect packages while they are installed in
# development mode). The CLI is used below to generate some of the help
# text.
subprocess.run(['qiime', 'dev', 'refresh-cache'], check=True)

plugins = qiime2.sdk.PluginManager().plugins
loader = jinja2.PackageLoader('sphinx_extensions.plugin_directory',
'templates')
Expand All @@ -32,47 +42,41 @@ def generate_rst(app):
fh.write(rendered)

for plugin in plugins.values():
plugin_dir = os.path.join(rst_dir, plugin.name)
plugin_cli_name = plugin.name.replace('_', '-')
plugin_dir = os.path.join(rst_dir, plugin_cli_name)
os.mkdir(plugin_dir)

index_path = os.path.join(plugin_dir, 'index.rst')
with open(index_path, 'w') as fh:
template = env.get_template('plugin.rst')
rendered = template.render(plugin=plugin)
rendered = template.render(title=plugin_cli_name, plugin=plugin)
fh.write(rendered)

for action in plugin.actions.values():
action_path = os.path.join(plugin_dir, '%s.rst' % action.id)
with open(action_path, 'w') as fh:
title = '%s: %s' % (action.id, action.name)
action_cli_name = action.id.replace('_', '-')
action_path = os.path.join(plugin_dir, '%s.rst' % action_cli_name)

input_specs = _get_param_specs(action.signature, 'inputs')
parameter_specs = _get_param_specs(action.signature,
'parameters')
output_specs = _get_param_specs(action.signature, 'outputs',
no_default='N/A')
with open(action_path, 'w') as fh:
title = '%s: %s' % (action_cli_name, action.name)
directive_indent = ' ' * 3

app.info("Generating help text for `%s %s`..." %
(plugin_cli_name, action_cli_name))
command = ['qiime', plugin_cli_name, action_cli_name, '--help']
proc = subprocess.run(command, check=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
cli_help = textwrap.indent(proc.stdout.decode('utf-8'),
directive_indent).strip()
api_help = textwrap.indent(action.__call__.__doc__,
directive_indent).strip()

template = env.get_template('action.rst')
rendered = template.render(action=action, title=title,
input_specs=input_specs,
parameter_specs=parameter_specs,
output_specs=output_specs)
rendered = template.render(title=title, cli_help=cli_help,
api_help=api_help)
fh.write(rendered)


def _get_param_specs(signature, group, no_default='Required'):
specs = []
for name, spec in getattr(signature, group).items():
default = no_default
if spec.has_default():
default = spec.default
description = 'No description'
if spec.has_description():
description = spec.description
specs.append((name, spec.qiime_type, default, description))
return specs


def cleanup_rst(app, exception):
if hasattr(app, 'plugin_directory_rst_dir') and \
os.path.exists(app.plugin_directory_rst_dir):
Expand Down
61 changes: 18 additions & 43 deletions source/sphinx_extensions/plugin_directory/templates/action.rst
Original file line number Diff line number Diff line change
@@ -1,48 +1,23 @@
{{ title }}
{{ '=' * title|length }}

{{ action.description }}

.. raw:: html

<table class="table action-signature">
{% for group, specs in (('Inputs', input_specs),
('Parameters', parameter_specs),
('Outputs', output_specs)) %}
<thead>
<tr>
<th colspan="4">{{ group }}</th>
</tr>
{% if specs %}
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
{% else %}
<tr>
<th colspan="4" class="text-muted">N/A</th>
</tr>
{% endif %}
</thead>
<tbody>
{% for spec in specs %}
<tr>
{% for content in spec[:3] %}
<td>
<code class="docutils literal">
<span class="pre">{{ content }}</span>
</code>
</td>
{% endfor %}
<td>
{% for line in spec[3].splitlines() %}
{{ line|urlize }}<br/>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
<div class="tabbed">
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#cli">Command line interface</a></li>
<li><a data-toggle="tab" href="#api">Artifact API</a></li>
</ul>
<div class="tab-content">
<div id="cli" class="tab-pane fade in active">
<pre>
{{- cli_help -}}
</pre>
</div>
<div id="api" class="tab-pane fade">
<pre>
{{- api_help -}}
</pre>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ QIIME 2 microbiome analysis functionality is made available to users via plugins
:maxdepth: 3

{% for name, plugin in plugins|dictsort %}
{% set cli_name = name.replace('_', '-') %}
{% if plugin.short_description %}
{{ name }}: {{ plugin.short_description }} <{{ name }}/index>
{{ cli_name }}: {{ plugin.short_description }} <{{ cli_name }}/index>
{% else %}
{{ name }}/index
{{ cli_name }}/index
{% endif %}
{% endfor %}

14 changes: 7 additions & 7 deletions source/sphinx_extensions/plugin_directory/templates/plugin.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{ plugin.name }}
{{ '=' * plugin.name|length }}
{{ title }}
{{ '=' * title|length }}

.. raw:: html

Expand All @@ -8,9 +8,9 @@
<tr>
<th scope="row">Description</th>
<td>
{% for line in plugin.description.splitlines() %}
{{ line|urlize }}<br/>
{% endfor %}
{% for line in plugin.description.splitlines() %}
{{ line|urlize }}<br/>
{% endfor %}
</td>
</tr>
<tr>
Expand Down Expand Up @@ -48,7 +48,7 @@ Methods
:maxdepth: 1

{% for id, _ in plugin.methods|dictsort %}
{{ id }}
{{ id.replace('_', '-') }}
{% endfor %}
{% else %}
This plugin does not have any methods.
Expand All @@ -62,7 +62,7 @@ Visualizers
:maxdepth: 1

{% for id, _ in plugin.visualizers|dictsort %}
{{ id }}
{{ id.replace('_', '-') }}
{% endfor %}
{% else %}
This plugin does not have any visualizers.
Expand Down
5 changes: 0 additions & 5 deletions source/theme/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,6 @@ div.admonition.qiime1 {
border: 1px solid #FAEBCC;
}

/* `plugin_directory` extension */
.action-signature th[colspan] {
text-align: center;
}

/* `tabbed` content */
.tabbed .white-bg {
background-color: #FFFFFF !important;
Expand Down

0 comments on commit d08a5a7

Please sign in to comment.