Skip to content

Commit a6584ae

Browse files
committed
Ensure that plugins preserve directory order
1 parent c020e12 commit a6584ae

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

paths_cli/cli.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,38 @@
1+
"""OpenPathSampling command line interface
2+
3+
This contains the "main" class/functions for running the OPS CLI.
4+
"""
15
# builds off the example of MultiCommand in click's docs
26
import collections
3-
import click
47
import os
58

6-
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
9+
import click
710

8-
plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')
11+
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
912

10-
_possible_plugin_folders = list(set([
13+
_POSSIBLE_PLUGIN_FOLDERS = [
1114
os.path.join(os.path.dirname(__file__), 'commands'),
1215
os.path.join(click.get_app_dir("OpenPathSampling"), 'cli-plugins'),
1316
os.path.join(click.get_app_dir("OpenPathSampling", force_posix=True),
1417
'cli-plugins'),
15-
]))
18+
]
1619

1720
OPSPlugin = collections.namedtuple("OPSPlugin",
1821
['name', 'filename', 'func', 'section'])
1922

23+
2024
class OpenPathSamplingCLI(click.MultiCommand):
25+
"""Main class for the command line interface
26+
27+
Most of the logic here is about handling the plugin infrastructure.
28+
"""
2129
def __init__(self, *args, **kwargs):
2230
# the logic here is all about loading the plugins
23-
plugin_folders = [
24-
os.path.join(os.path.dirname(__file__), 'commands'),
25-
os.path.join(click.get_app_dir("OpenPathSampling",
26-
force_posix=True),
27-
'cli-plugins')
28-
]
29-
self.plugin_folders = [f for f in _possible_plugin_folders
30-
if os.path.exists(f)]
31+
self.plugin_folders = []
32+
for folder in _POSSIBLE_PLUGIN_FOLDERS:
33+
if folder not in self.plugin_folders and os.path.exists(folder):
34+
self.plugin_folders.append(folder)
35+
3136
plugin_files = self._list_plugin_files(self.plugin_folders)
3237
self.plugins = self._load_plugin_files(plugin_files)
3338

@@ -65,7 +70,7 @@ def _load_plugin(name):
6570
def _load_plugin_files(self, plugin_files):
6671
plugins = []
6772
for full_name in plugin_files:
68-
head, filename = os.path.split(full_name)
73+
_, filename = os.path.split(full_name)
6974
command_name = self._filename_to_command_name(filename)
7075
func, section = self._load_plugin(full_name)
7176
plugins.append(OPSPlugin(name=command_name, filename=full_name,
@@ -95,7 +100,7 @@ def format_commands(self, ctx, formatter):
95100
formatter.write_dl(rows)
96101

97102

98-
main_help="""
103+
_MAIN_HELP = """
99104
OpenPathSampling is a Python library for path sampling simulations. This
100105
command line tool facilitates common tasks when working with
101106
OpenPathSampling. To use it, use one of the subcommands below. For example,
@@ -105,14 +110,16 @@ def format_commands(self, ctx, formatter):
105110
openpathsampling strip-snapshots --help
106111
"""
107112

113+
108114
def main(): # no-cov
109115
cli = OpenPathSamplingCLI(
110116
name="openpathsampling",
111-
help=main_help,
117+
help=_MAIN_HELP,
112118
context_settings=CONTEXT_SETTINGS
113119
)
114120
cli()
115121

122+
116123
if __name__ == '__main__': # no-cov
117124
main()
118125
# print("list commands:", cli.list_commands())

0 commit comments

Comments
 (0)