Skip to content

Commit c020e12

Browse files
committed
new (and working!) plugin framework
1 parent ae59253 commit c020e12

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

paths_cli/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .cli import OpenPathSamplingCLI

paths_cli/cli.py

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,76 @@
77

88
plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')
99

10+
_possible_plugin_folders = list(set([
11+
os.path.join(os.path.dirname(__file__), 'commands'),
12+
os.path.join(click.get_app_dir("OpenPathSampling"), 'cli-plugins'),
13+
os.path.join(click.get_app_dir("OpenPathSampling", force_posix=True),
14+
'cli-plugins'),
15+
]))
16+
17+
OPSPlugin = collections.namedtuple("OPSPlugin",
18+
['name', 'filename', 'func', 'section'])
19+
1020
class OpenPathSamplingCLI(click.MultiCommand):
1121
def __init__(self, *args, **kwargs):
12-
self.plugin_folders = [
22+
# the logic here is all about loading the plugins
23+
plugin_folders = [
1324
os.path.join(os.path.dirname(__file__), 'commands'),
1425
os.path.join(click.get_app_dir("OpenPathSampling",
1526
force_posix=True),
1627
'cli-plugins')
1728
]
29+
self.plugin_folders = [f for f in _possible_plugin_folders
30+
if os.path.exists(f)]
31+
plugin_files = self._list_plugin_files(self.plugin_folders)
32+
self.plugins = self._load_plugin_files(plugin_files)
33+
1834
self._get_command = {}
1935
self._sections = collections.defaultdict(list)
20-
plugin_files, command_list = self._list_plugins()
21-
for cmd, plugin_file in zip(command_list, plugin_files):
22-
command, section = self._load_plugin(plugin_file)
23-
self._get_command[cmd] = command
24-
self._sections[section].append(cmd)
36+
for plugin in self.plugins:
37+
self._get_command[plugin.name] = plugin.func
38+
self._sections[plugin.section].append(plugin.name)
39+
2540
super(OpenPathSamplingCLI, self).__init__(*args, **kwargs)
2641

27-
def _load_plugin(self, name):
42+
@staticmethod
43+
def _list_plugin_files(plugin_folders):
44+
plugin_files = []
45+
for folder in plugin_folders:
46+
files = [os.path.join(folder, f) for f in os.listdir(folder)
47+
if f.endswith(".py")]
48+
plugin_files += files
49+
return plugin_files
50+
51+
@staticmethod
52+
def _filename_to_command_name(filename):
53+
command_name = filename[:-3] # get rid of .py
54+
command_name = command_name.replace('_', '-') # commands use -
55+
return command_name
56+
57+
@staticmethod
58+
def _load_plugin(name):
2859
ns = {}
29-
fn = os.path.join(plugin_folder, name + '.py')
30-
with open(fn) as f:
31-
code = compile(f.read(), fn, 'exec')
60+
with open(name) as f:
61+
code = compile(f.read(), name, 'exec')
3262
eval(code, ns, ns)
3363
return ns['CLI'], ns['SECTION']
3464

35-
def _list_plugins(self):
36-
files = []
37-
commands = []
38-
for filename in os.listdir(plugin_folder):
39-
if filename.endswith('.py'):
40-
command = filename.replace('_', '-')
41-
files.append(filename[:-3])
42-
commands.append(command[:-3])
43-
return files, commands
65+
def _load_plugin_files(self, plugin_files):
66+
plugins = []
67+
for full_name in plugin_files:
68+
head, filename = os.path.split(full_name)
69+
command_name = self._filename_to_command_name(filename)
70+
func, section = self._load_plugin(full_name)
71+
plugins.append(OPSPlugin(name=command_name, filename=full_name,
72+
func=func, section=section))
73+
return plugins
4474

4575
def list_commands(self, ctx):
4676
return list(self._get_command.keys())
4777

4878
def get_command(self, ctx, name):
49-
name = name.replace('_', '-') # auto alias to allow - or _
79+
name = name.replace('_', '-') # allow - or _ from user
5080
return self._get_command.get(name)
5181

5282
def format_commands(self, ctx, formatter):

0 commit comments

Comments
 (0)