Exemple #1
0
class batch(Command):
    NO_CLI = True

    takes_args = (
        Any('methods*',
            doc=_('Nested Methods to execute'),
        ),
    )

    take_options = (
        Str('version',
            cli_name='version',
            doc=_('Client version. Used to determine if server will accept request.'),
            exclude='webui',
            flags=['no_option', 'no_output'],
            default=API_VERSION,
            autofill=True,
        ),
    )

    has_output = (
        Output('count', int, doc=''),
        Output('results', (list, tuple), doc='')
    )

    def execute(self, *args, **options):
        results = []
        for arg in args[0]:
            params = dict()
            name = None
            try:
                if 'method' not in arg:
                    raise errors.RequirementError(name='method')
                if 'params' not in arg:
                    raise errors.RequirementError(name='params')
                name = arg['method']
                if name not in self.Command:
                    raise errors.CommandError(name=name)
                a, kw = arg['params']
                newkw = dict((str(k), v) for k, v in kw.items())
                params = api.Command[name].args_options_2_params(*a, **newkw)
                newkw.setdefault('version', options['version'])

                result = api.Command[name](*a, **newkw)
                self.info(
                    '%s: batch: %s(%s): SUCCESS', context.principal, name, ', '.join(api.Command[name]._repr_iter(**params))
                )
                result['error']=None
            except Exception as e:
                if isinstance(e, errors.RequirementError) or \
                    isinstance(e, errors.CommandError):
                    self.info(
                        '%s: batch: %s',
                        context.principal,  # pylint: disable=no-member
                        e.__class__.__name__
                    )
                else:
                    self.info(
                        '%s: batch: %s(%s): %s',
                        context.principal, name,  # pylint: disable=no-member
                        ', '.join(api.Command[name]._repr_iter(**params)),
                        e.__class__.__name__
                    )
                if isinstance(e, errors.PublicError):
                    reported_error = e
                else:
                    reported_error = errors.InternalError()
                result = dict(
                    error=reported_error.strerror,
                    error_code=reported_error.errno,
                    error_name=unicode(type(reported_error).__name__),
                )
            results.append(result)
        return dict(count=len(results) , results=results)
Exemple #2
0
class help(frontend.Local):
    """
    Display help for a command or topic.
    """
    class Writer(object):
        """
        Writer abstraction
        """
        def __init__(self, outfile):
            self.outfile = outfile
            self.buffer = []

        @property
        def buffer_length(self):
            length = 0
            for line in self.buffer:
                length += len(line.split("\n"))
            return length

        def append(self, string=u""):
            self.buffer.append(unicode(string))

        def write(self):
            if self.buffer_length > get_terminal_height():
                data = "\n".join(self.buffer).encode("utf-8")
                open_in_pager(data)
            else:
                try:
                    for line in self.buffer:
                        print(line, file=self.outfile)
                except IOError:
                    pass

    takes_args = (
        Str('command?', cli_name='topic', label=_('Topic or Command'),
            doc=_('The topic or command name.')),
    )
    takes_options = (
        Any('outfile?', flags=['no_option']),
    )

    has_output = tuple()

    topic = None

    def _get_topic(self, topic):
        doc = u''
        parent_topic = None

        for package in self.api.packages:
            module_name = '{0}.{1}'.format(package.__name__, topic)
            try:
                module = sys.modules[module_name]
            except KeyError:
                try:
                    module = importlib.import_module(module_name)
                except ImportError:
                    continue

            if module.__doc__ is not None:
                doc = unicode(module.__doc__ or '').strip()
            try:
                parent_topic = module.topic
            except AttributeError:
                pass

        return doc, parent_topic

    def _count_topic_mcl(self, topic_name, mod_name):
        mcl = max((self._topics[topic_name][1], len(mod_name)))
        self._topics[topic_name][1] = mcl

    def _on_finalize(self):
        # {topic: ["description", mcl, {
        #     "subtopic": ["description", mcl, [commands]]}]}
        # {topic: ["description", mcl, [commands]]}
        self._topics = {}
        # [builtin_commands]
        self._builtins = []

        # build help topics
        for c in self.api.Command:
            if c is not self.api.Command.get_plugin(c.name):
                continue
            if c.NO_CLI:
                continue

            if c.topic is not None:
                doc, topic_name = self._get_topic(c.topic)
                doc = doc.split('\n', 1)[0]
                if topic_name is None:  # a module without grouping
                    topic_name = c.topic
                    if topic_name in self._topics:
                        self._topics[topic_name][2].append(c)
                    else:
                        self._topics[topic_name] = [doc, 0, [c]]
                    mcl = max((self._topics[topic_name][1], len(c.name)))
                    self._topics[topic_name][1] = mcl
                else:  # a module grouped in a topic
                    topic = self._get_topic(topic_name)
                    mod_name = c.topic
                    if topic_name in self._topics:
                        if mod_name in self._topics[topic_name][2]:
                            self._topics[topic_name][2][mod_name][2].append(c)
                        else:
                            self._topics[topic_name][2][mod_name] = [
                                doc, 0, [c]]
                            self._count_topic_mcl(topic_name, mod_name)
                        # count mcl for for the subtopic
                        mcl = max((
                            self._topics[topic_name][2][mod_name][1],
                            len(c.name)))
                        self._topics[topic_name][2][mod_name][1] = mcl
                    else:
                        self._topics[topic_name] = [
                            topic[0].split('\n', 1)[0],
                            0,
                            {mod_name: [doc, 0, [c]]}]
                        self._count_topic_mcl(topic_name, mod_name)
            else:
                self._builtins.append(c)

        # compute maximum topic length
        topics = list(self._topics) + [c.name for c in self._builtins]
        self._mtl = max(len(s) for s in topics)

        super(help, self)._on_finalize()

    def run(self, key=None, outfile=None, **options):
        if outfile is None:
            outfile = sys.stdout

        writer = self.Writer(outfile)
        name = from_cli(key)

        if key is None:
            self.api.parser.print_help(outfile)
            return
        if name == "topics":
            self.print_topics(outfile)
            return
        if name in self._topics:
            self.print_commands(name, outfile)
        elif name in self.Command:
            cmd = self.Command[name]
            if cmd.NO_CLI:
                raise HelpError(topic=name)
            self.Backend.cli.build_parser(cmd).print_help(outfile)
        elif any(name in t[2] for t in self._topics.values()
                 if type(t[2]) is dict):
            self.print_commands(name, outfile)
        elif name == "commands":
            mcl = 0
            for cmd_plugin in self.Command:
                if cmd_plugin is not self.Command.get_plugin(cmd_plugin.name):
                    continue
                if cmd_plugin.NO_CLI:
                    continue
                mcl = max(mcl, len(cmd_plugin.name))
                writer.append('{0}  {1}'.format(
                    to_cli(cmd_plugin.name).ljust(mcl), cmd_plugin.summary))
        else:
            raise HelpError(topic=name)
        writer.write()

    def print_topics(self, outfile):
        writer = self.Writer(outfile)

        for t, topic in sorted(self._topics.items()):
            writer.append('{0}  {1}'.format(
                to_cli(t).ljust(self._mtl), topic[0]))
        writer.write()

    def print_commands(self, topic, outfile):
        writer = self.Writer(outfile)

        if topic in self._topics and type(self._topics[topic][2]) is dict:
            # we want to display topic which has subtopics
            for subtopic in self._topics[topic][2]:
                doc = self._topics[topic][2][subtopic][0]
                mcl = self._topics[topic][1]
                writer.append('  {0}  {1}'.format(
                    to_cli(subtopic).ljust(mcl), doc))
        else:
            # we want to display subtopic or a topic which has no subtopics
            if topic in self._topics:
                mcl = self._topics[topic][1]
                commands = self._topics[topic][2]
            else:
                commands = []
                for t in self._topics:
                    if type(self._topics[t][2]) is not dict:
                        continue
                    if topic not in self._topics[t][2]:
                        continue
                    mcl = self._topics[t][2][topic][1]
                    commands = self._topics[t][2][topic][2]
                    break

            doc, _topic = self._get_topic(topic)

            if topic not in self.Command and len(commands) == 0:
                raise HelpError(topic=topic)

            writer.append(doc)
            if commands:
                writer.append()
                writer.append(_('Topic commands:'))
                for c in commands:
                    writer.append(
                        '  {0}  {1}'.format(
                            to_cli(c.name).ljust(mcl), c.summary))
                writer.append()
                writer.append(_('To get command help, use:'))
                writer.append(_('  ipa <command> --help'))
            writer.append()
        writer.write()
Exemple #3
0
class help(frontend.Local):
    """
    Display help for a command or topic.
    """

    takes_args = (Str('command?',
                      cli_name='topic',
                      label=_('Topic or Command'),
                      doc=_('The topic or command name.')), )
    takes_options = (Any('outfile?', flags=['no_option']), )

    has_output = tuple()

    _PLUGIN_BASE_MODULE = 'ipalib.plugins'

    def _get_command_module(self, module):
        """
        Return last part of ``module`` name, or ``None`` if module is this file.

        For example:
        """
        if module == __name__:
            return
        return module.split('.')[-1]

    def _get_module_topic(self, module_name):
        if not sys.modules[module_name]:
            __import__(module_name)
        module = sys.modules[module_name]

        topic = getattr(module, 'topic', None)
        if topic is None:
            topic = (self._get_command_module(module_name), None)

        return topic

    def _count_topic_mcl(self, topic_name, mod_name):
        mcl = max((self._topics[topic_name][1], len(mod_name)))
        self._topics[topic_name][1] = mcl

    def _on_finalize(self):
        # {topic: ["description", mcl, {"subtopic": ["description", mcl, [commands]]}]}
        # {topic: ["description", mcl, [commands]]}
        self._topics = {}
        # [builtin_commands]
        self._builtins = []

        # build help topics
        for c in self.api.Command():
            if c.NO_CLI:
                continue

            topic = self._get_module_topic(c.module)
            topic_name = topic[0]

            if topic_name:
                if topic[1] is None:  # a module without grouping
                    if topic_name in self._topics:
                        self._topics[topic_name][2].append(c)
                    else:
                        m = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic_name)
                        try:
                            module = sys.modules[m]
                        except KeyError:
                            doc = ''
                        else:
                            doc = (unicode(_(module.__doc__))
                                   or '').strip().split('\n', 1)[0]
                        self._topics[topic_name] = [doc, 0, [c]]
                    mcl = max((self._topics[topic_name][1], len(c.name)))
                    self._topics[topic_name][1] = mcl
                else:  # a module grouped in a topic
                    doc = (unicode(_(sys.modules[c.module].__doc__))
                           or '').strip().split('\n', 1)[0]
                    mod_name = c.module.rsplit('.', 1)[1]
                    if topic_name in self._topics:
                        if mod_name in self._topics[topic_name][2]:
                            self._topics[topic_name][2][mod_name][2].append(c)
                        else:
                            self._topics[topic_name][2][mod_name] = [
                                doc, 0, [c]
                            ]
                            self._count_topic_mcl(topic_name, mod_name)
                        # count mcl for for the subtopic
                        mcl = max((self._topics[topic_name][2][mod_name][1],
                                   len(c.name)))
                        self._topics[topic_name][2][mod_name][1] = mcl
                    else:
                        self._topics[topic_name] = [
                            unicode(_(topic[1])), 0, {
                                mod_name: [doc, 0, [c]]
                            }
                        ]
                        self._count_topic_mcl(topic_name, mod_name)
            else:
                self._builtins.append(c)

        # compute maximum topic length
        topics = list(self._topics) + [c.name for c in self._builtins]
        self._mtl = max(len(s) for s in topics)

        super(help, self)._on_finalize()

    def run(self, key, outfile=None, **options):
        if outfile is None:
            outfile = sys.stdout
        writer = self._writer(outfile)
        name = from_cli(key)
        mod_name = '%s.%s' % (self._PLUGIN_BASE_MODULE, name)
        if key is None:
            self.api.parser.print_help(outfile)
            return
        if name == "topics":
            self.print_topics(outfile)
            return
        if name in self._topics:
            self.print_commands(name, outfile)
        elif name in self.Command:
            cmd = self.Command[name]
            if cmd.NO_CLI:
                raise HelpError(topic=name)
            self.Backend.cli.build_parser(cmd).print_help(outfile)
        elif mod_name in sys.modules:
            self.print_commands(name, outfile)
        elif name == "commands":
            mcl = max(len(s) for s in (self.Command))
            for cname in self.Command:
                cmd = self.Command[cname]
                if cmd.NO_CLI:
                    continue
                writer('%s  %s' % (to_cli(cmd.name).ljust(mcl), cmd.summary))
        else:
            raise HelpError(topic=name)

    def _writer(self, outfile):
        def writer(string=''):
            try:
                print(unicode(string), file=outfile)
            except IOError:
                pass

        return writer

    def print_topics(self, outfile):
        writer = self._writer(outfile)

        for t, topic in sorted(self._topics.items()):
            writer('%s  %s' % (to_cli(t).ljust(self._mtl), topic[0]))

    def print_commands(self, topic, outfile):
        writer = self._writer(outfile)
        if topic in self._topics and type(self._topics[topic][2]) is dict:
            # we want to display topic which has subtopics
            for subtopic in self._topics[topic][2]:
                doc = self._topics[topic][2][subtopic][0]
                mcl = self._topics[topic][1]
                writer('  %s  %s' % (to_cli(subtopic).ljust(mcl), doc))
        else:
            # we want to display subtopic or a topic which has no subtopics
            if topic in self._topics:
                mcl = self._topics[topic][1]
                commands = self._topics[topic][2]
            else:
                commands = []
                for t in self._topics:
                    if type(self._topics[t][2]) is not dict:
                        continue
                    if topic not in self._topics[t][2]:
                        continue
                    mcl = self._topics[t][2][topic][1]
                    commands = self._topics[t][2][topic][2]
                    break

            m = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic)
            doc = (unicode(_(sys.modules[m].__doc__)) or '').strip()

            if topic not in self.Command and len(commands) == 0:
                raise HelpError(topic=topic)

            writer(doc)
            if commands:
                writer()
                writer(_('Topic commands:'))
                for c in commands:
                    writer('  %s  %s' % (to_cli(c.name).ljust(mcl), c.summary))
                writer()
                writer(_('To get command help, use:'))
                writer(_('  ipa <command> --help'))
            writer()