def testFilterAll__get_registered(self): """ registration.get_registered: returns all registered plugins. """ registration._registered.register(MockPlugin.name, MockPlugin, {'command': True}) self.assertIn(MockPlugin.name, [x.name for x in registration.get_registered()])
def testFilterActiveTask__get_registered(self): """ registration.get_registered: returns all registered plugins that are available when a task is active. """ class MockPlugin2(MockPlugin): name = 'hai 2' options = None class MockPlugin3(MockPlugin): name = 'hai 3' options = None task_only = True # register a couple test plugins registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) registration._registered.register(MockPlugin3.name, MockPlugin3, {'command': True}) # get list of registered names for active task plugins plugin_names = [ x.name for x in registration.get_registered(task_active=True) ] self.assertIn(MockPlugin.name, plugin_names) self.assertIn(MockPlugin2.name, plugin_names) self.assertIn(MockPlugin3.name, plugin_names)
def testFilterNoActiveTask__get_registered(self): """ registration.get_registered: returns all registered plugins that can be seen when a task is not active. """ class MockPlugin2(MockPlugin): name = 'hai 2' options = None class MockPlugin3(MockPlugin): name = 'hai 3' options = None task_only = True # register a couple test plugins registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) registration._registered.register(MockPlugin3.name, MockPlugin3, {'command': True}) # get list of registered names for active task plugins plugin_names = [ x.name for x in registration.get_registered(task_active=False) ] # check that only the non-option, task_only=False plugin is returned self.assertIn(MockPlugin2.name, plugin_names) self.assertNotIn(MockPlugin.name, plugin_names) self.assertNotIn(MockPlugin3.name, plugin_names)
def testFilterActiveTask__get_registered(self): """ registration.get_registered: returns all registered plugins that are available when a task is active. """ class MockPlugin2(MockPlugin): name = 'hai 2' options = None class MockPlugin3(MockPlugin): name = 'hai 3' options = None task_only = True # register a couple test plugins registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) registration._registered.register(MockPlugin3.name, MockPlugin3, {'command': True}) # get list of registered names for active task plugins plugin_names = [x.name for x in registration.get_registered(task_active=True)] self.assertIn(MockPlugin.name, plugin_names) self.assertIn(MockPlugin2.name, plugin_names) self.assertIn(MockPlugin3.name, plugin_names)
def testFilterNoActiveTask__get_registered(self): """ registration.get_registered: returns all registered plugins that can be seen when a task is not active. """ class MockPlugin2(MockPlugin): name = 'hai 2' options = None class MockPlugin3(MockPlugin): name = 'hai 3' options = None task_only = True # register a couple test plugins registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) registration._registered.register(MockPlugin3.name, MockPlugin3, {'command': True}) # get list of registered names for active task plugins plugin_names = [x.name for x in registration.get_registered(task_active=False)] # check that only the non-option, task_only=False plugin is returned self.assertIn(MockPlugin2.name, plugin_names) self.assertNotIn(MockPlugin.name, plugin_names) self.assertNotIn(MockPlugin3.name, plugin_names)
def shell_focusd(data_dir): """ Shells a new instance of a focusd daemon process. `data_dir` Home directory for focusd data. Returns boolean. * Raises ``ValueError`` if sudo used and all passwords tries failed. """ command = 'focusd {0}'.format(data_dir) # see what event hook plugins are registered plugins = registration.get_registered(event_hooks=True) if not plugins: # none registered, bail raise errors.NoPluginsRegistered # do any of the plugins need root access? # if so, wrap command with sudo to escalate privs, if not already root needs_root = any(p for p in plugins if p.needs_root) if needs_root and os.getuid() != 0: # only if not already root command = 'sudo ' + command else: needs_root = False # shell the daemon process _, code = common.shell_process(command, exitcode=True) if code == 1 and needs_root: # passwords failed? raise ValueError return code == 0
def _prepare(self): """ Setup initial requirements for daemon run. """ super(CommandServer, self)._prepare() # unregister all active plugins for plugin in registration.get_registered(): registration.disable_plugin_instance(plugin)
def focusd(task): """ Forks the current process as a daemon to run a task. `task` ``Task`` instance for the task to run. """ # determine if command server should be started if registration.get_registered(event_hooks=True, root_access=True): # root event plugins available start_cmd_srv = (os.getuid() == 0) # must be root else: start_cmd_srv = False # daemonize our current process _run = lambda: Focusd(task).run(start_cmd_srv) daemonize(get_daemon_pidfile(task), task.task_dir, _run)
def testGoodPlugins__load(self): """ Environment.load: successfully loads valid plugins. """ # build test command plugin and load plugin_dir = os.path.join(self.env._data_dir, 'plugins') os.makedirs(plugin_dir) filename = os.path.join(plugin_dir, 'testplugin.py') with open(filename, 'w', 0) as f: f.write('from focus.plugin import Plugin\n') f.write('class MyTestPlugin(Plugin):\n') f.write(' name = "MyTestPlugin"\n') f.write(' target_version = ">=0.1.0"\n') f.write(' version = "1.0"\n') f.write(' command = "oh_hai"\n') f.write(' def execute(self, env): env.io.write("You rang.")\n') f.write(' def help(self, env): return u"focus oh_hai"\n') self.env.load() # confirm plugin registration in a couple ways.. # 1) scan registered list # 2) get command hook version # 3) execute methods and compare plugin = None for p in registration.get_registered(command_hooks=True): if p.name == 'MyTestPlugin': plugin = p break success = False if plugin: test_plugin = registration.get_command_hook('oh_hai') if test_plugin == plugin: # test execute() plugin.execute(self.env) self.assertEqual(self.env.io.test__write_data, 'You rang.\n') # test help() data = plugin.help(self.env) self.assertEqual(data, u'focus oh_hai') success = True self.assertTrue(success) # clean up self.clean_paths(filename, filename + 'c')
def testFilterEventHook__get_registered(self): """ registration.get_registered: returns all registered task event plugins. """ class MockPlugin2(MockPlugin): name = 'hai 2' # register a command and event plugin registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) # get list of registered names for event plugins plugin_names = [x.name for x in registration.get_registered(event_hooks=True)] # make sure MockPlugin is the only event plugin self.assertIn(MockPlugin.name, plugin_names) self.assertNotIn(MockPlugin2.name, plugin_names)
def testFilterEventHook__get_registered(self): """ registration.get_registered: returns all registered task event plugins. """ class MockPlugin2(MockPlugin): name = 'hai 2' # register a command and event plugin registration._registered.register(MockPlugin.name, MockPlugin, {'event': True}) registration._registered.register(MockPlugin2.name, MockPlugin2, {'command': True}) # get list of registered names for event plugins plugin_names = [ x.name for x in registration.get_registered(event_hooks=True) ] # make sure MockPlugin is the only event plugin self.assertIn(MockPlugin.name, plugin_names) self.assertNotIn(MockPlugin2.name, plugin_names)
def _setup_root_plugins(self): """ Injects a `run_root` method into the registered root event plugins. """ def run_root(_self, command): """ Executes a shell command as root. `command` Shell command string. Returns boolean. """ try: # get lock, so this plugin has exclusive access to command pipe self._rlock.acquire() # TODO: log root command for this plugin self._cmd_pipe.send_bytes('\x80'.join(['SHL', command])) res = self._cmd_pipe.recv_bytes() if res != 'TRM': # sentinel value, shutdown return res == 'OK' except (EOFError, IOError): pass finally: self._rlock.release() self.shutdown(skip_hooks=True) return False # inject method into each event plugin for plugin in registration.get_registered(event_hooks=True, root_access=True): plugin.run_root = types.MethodType(run_root, plugin)
def _get_parser(self, env): """ Creates base argument parser. `env` Runtime ``Environment`` instance. * Raises ``HelpBanner`` exception when certain conditions apply. Returns ``FocusArgumentParser`` object. """ version_str = 'focus version ' + __version__ usage_str = 'focus [-h] [-v] [--no-color] <command> [<args>]' # setup parser parser = FocusArgParser(description=("Command-line productivity tool " "for improved task workflows."), epilog=("See 'focus help <command>' for more " "information on a specific command."), usage=usage_str) parser.add_argument('-v', '--version', action='version', version=version_str) parser.add_argument('--no-color', action='store_true', help='disables colors') # fetch command plugins commands = [] active = env.task.active command_hooks = registration.get_registered(command_hooks=True, task_active=active) # extract command name and docstrings as help text for plugin in command_hooks: help_text = (plugin.__doc__ or '').strip().rstrip('.').lower() commands.append((plugin.command, help_text)) commands.sort(key=lambda x: x[0]) # command ordered # install subparsers subparsers = parser.add_subparsers(title='available commands') # install 'help' subparser help_parser = subparsers.add_parser('help', add_help=False) help_parser.set_defaults(func=self._handle_help) # install 'version' subparser version_parser = subparsers.add_parser('version', add_help=False) def _print_version(env, args): env.io.write(version_str) return True version_parser.set_defaults(func=_print_version) # install command subparsers based on registered command plugins. # this allows for focus commands (e.g. focus on [...]) for command, help_ in commands: cmd_parser = subparsers.add_parser(command, help=help_, add_help=False) # use wrapper to bind command value and passthru to _handle_command # when executed later def _run(command): def _wrapper(env, args): return self._handle_command(command, env, args) return _wrapper cmd_parser.set_defaults(func=_run(command)) return parser