-
-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,12 @@ | |
|
||
import os | ||
import sys | ||
import itertools | ||
import traceback | ||
import importlib | ||
from collections import defaultdict | ||
import six | ||
from six.moves import configparser | ||
|
||
from .version import VERSION | ||
from .exceptions import InvalidDodoFile, InvalidCommand, InvalidTask | ||
|
@@ -37,14 +41,55 @@ def set_var(name, value): | |
|
||
|
||
|
||
class PluginRegistry(object): | ||
"""simple plugin system to load code dynamically | ||
Plugins must be explicitly loaded (no scanning of files and folders is done | ||
to find plugins). | ||
There is no requirements of interface or checking of loaded plugins (that's | ||
up to application code if desirable). The registry is responsible only for | ||
loading a piece of code and keeping a reference to it. | ||
""" | ||
def __init__(self): | ||
self._plugins = defaultdict(list) # category: value | ||
|
||
def __getitem__(self, key): | ||
"""get all plugins from a given category""" | ||
return self._plugins[key] | ||
|
||
def add(self, category, module_name, obj_name): | ||
"""get reference to obj from named module/obj""" | ||
module = importlib.import_module(module_name) | ||
self._plugins[category].append(getattr(module, obj_name)) | ||
|
||
|
||
|
||
class DoitMain(object): | ||
DOIT_CMDS = (Help, Run, List, Info, Clean, Forget, Ignore, Auto, DumpDB, | ||
Strace, TabCompletion) | ||
TASK_LOADER = DodoTaskLoader | ||
|
||
def __init__(self, task_loader=None): | ||
def __init__(self, task_loader=None, config_filenames='doit.cfg'): | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
schettino72
Author
Member
|
||
self.task_loader = task_loader if task_loader else self.TASK_LOADER() | ||
self.sub_cmds = {} # dict with available sub-commands | ||
self.plugins = PluginRegistry() | ||
self.config = configparser.SafeConfigParser(allow_no_value=True) | ||
self.config.optionxform = str # preserve case of option names | ||
self.load_config_ini(config_filenames) | ||
|
||
|
||
def load_config_ini(self, filenames): | ||
"""read config from INI files | ||
:param files: str or list of str. | ||
Like ConfigParser.read() param filenames | ||
""" | ||
self.config.read(filenames) | ||
for name, _ in self.config.items('command'): | ||
obj_name, mod_name = name.split('@') | ||
self.plugins.add('command', mod_name, obj_name) | ||
|
||
|
||
@staticmethod | ||
def print_version(): | ||
|
@@ -57,7 +102,7 @@ def get_commands(self): | |
"""get all sub-commands""" | ||
sub_cmds = {} | ||
# core doit commands | ||
for cmd_cls in (self.DOIT_CMDS): | ||
for cmd_cls in itertools.chain(self.DOIT_CMDS, self.plugins['command']): | ||
if issubclass(cmd_cls, DoitCmdBase): | ||
cmd = cmd_cls(task_loader=self.task_loader) | ||
cmd.doit_app = self # hack used by Help/TabComplete command | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[command] | ||
|
||
MyCmd@tests.sample_plugin | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from doit.cmd_base import Command | ||
|
||
class MyCmd(Command): | ||
name = 'mycmd' | ||
doc_purpose = 'test extending doit commands' | ||
doc_usage = '[XXX]' | ||
doc_description = 'my command description' | ||
|
||
def execute(self, opt_values, pos_args): # pragma: no cover | ||
print("this command does nothing!") |
Shouldn't it be either "hidden" file (
.doit.cfg
) or (dodo.cfg
)?