[Freeipa-devel] [PATCH] 372 Added attribute to specify command's CLI name.

Endi Sukma Dewata edewata at redhat.com
Mon Aug 10 18:35:29 UTC 2015


A new attribute has been added to the HasParams class to allow a
command to specify a different CLI name if necessary. By default
the command's CLI name is the same as the class name.

https://fedorahosted.org/freeipa/ticket/5189

-- 
Endi S. Dewata
-------------- next part --------------
From 6808e44b97148db8700e47d1d436dd0a30a0c9f9 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Fri, 7 Aug 2015 05:00:14 +0200
Subject: [PATCH] Added attribute to specify command's CLI name.

A new attribute has been added to the HasParams class to allow a
command to specify a different CLI name if necessary. By default
the command's CLI name is the same as the class name.

https://fedorahosted.org/freeipa/ticket/5189
---
 ipalib/backend.py  | 15 ++++++++++++--
 ipalib/cli.py      | 59 ++++++++++++++++++++++++++++++------------------------
 ipalib/frontend.py | 19 ++++++++++++++++++
 3 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/ipalib/backend.py b/ipalib/backend.py
index d510bc73396cd8b219836d28083e3165f226d466..48a4445c34a861d65e80f1fdaf711cbd0f643ae2 100644
--- a/ipalib/backend.py
+++ b/ipalib/backend.py
@@ -121,12 +121,23 @@ class Executioner(Backend):
     def destroy_context(self):
         destroy_context()
 
+    def find_command(self, cli_name):
+        # TODO: replace loop with a dict to map CLI names to commands
+        for name in self.Command:
+            cmd = self.Command[name]
+            if cmd.NO_CLI:
+                continue
+            if cmd.cli_name() == cli_name:
+                return cmd
+        return None
+
     def execute(self, _name, *args, **options):
         error = None
         try:
-            if _name not in self.Command:
+            cmd = self.find_command(_name)
+            if not cmd:
                 raise CommandError(name=_name)
-            result = self.Command[_name](*args, **options)
+            result = cmd(*args, **options)
         except PublicError, e:
             error = e
         except StandardError, e:
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 4104e6482e4e713d701c6c1a4313ab6ecc899057..0fa00d3a6e32fc6095ca3b76270355cf9cb3dd2d 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -771,32 +771,40 @@ class help(frontend.Local):
         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":
+
+        if key == "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":
+
+        if key in self._topics:
+            self.print_commands(key, outfile)
+            return
+
+        if key == "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)
+                writer('%s  %s' % (cmd.cli_name().ljust(mcl), cmd.summary))
+            return
+
+        cmd = self.find_command(key)
+        if cmd:
+            self.Backend.cli.build_parser(cmd).print_help(outfile)
+            return
+
+        name = from_cli(key)
+        mod_name = '%s.%s' % (self._PLUGIN_BASE_MODULE, name)
+        if mod_name in sys.modules:
+            self.print_commands(name, outfile)
+            return
+
+        raise HelpError(topic=key)
 
     def _writer(self, outfile):
         def writer(string=''):
@@ -848,7 +856,7 @@ class help(frontend.Local):
                 writer(_('Topic commands:'))
                 for c in commands:
                     writer(
-                        '  %s  %s' % (to_cli(c.name).ljust(mcl), c.summary))
+                        '  %s  %s' % (c.cli_name().ljust(mcl), c.summary))
                 writer()
                 writer(_('To get command help, use:'))
                 writer(_('  ipa <command> --help'))
@@ -866,10 +874,10 @@ class show_mappings(frontend.Command):
     has_output = tuple()
 
     def run(self, command_name, **options):
-        command_name = from_cli(command_name)
-        if command_name not in self.Command:
+        cmd = self.find_command(command_name)
+        if not cmd:
             raise CommandError(name=command_name)
-        params = self.Command[command_name].options
+        params = cmd.options
         out = [('Parameter','LDAP attribute'),
                ('=========','==============')]
         mcl = len(out[0][0])
@@ -1061,15 +1069,14 @@ class cli(backend.Executioner):
             print >>sys.stderr, 'Error: Command not specified'
             exit(2)
         (key, argv) = (argv[0], argv[1:])
-        name = from_cli(key)
-        if name not in self.Command and len(argv) == 0:
+        cmd = self.find_command(key)
+        if not cmd and len(argv) == 0:
             try:
                 self.Command.help(unicode(key), outfile=sys.stderr)
             except HelpError:
                 pass
-        if name not in self.Command or self.Command[name].NO_CLI:
+        if not cmd:
             raise CommandError(name=key)
-        cmd = self.Command[name]
         return cmd
 
     def process_keyword_arguments(self, cmd, kw):
@@ -1090,7 +1097,7 @@ class cli(backend.Executioner):
         cmd = self.get_command(argv)
         if cmd is None:
             return
-        name = cmd.name
+        name = cmd.cli_name()
         kw = self.parse(cmd, argv[1:])
         if not isinstance(cmd, frontend.Local):
             self.create_context()
@@ -1207,7 +1214,7 @@ class cli(backend.Executioner):
             return '[%s]' % name
 
     def usage_iter(self, cmd):
-        yield 'Usage: %%prog [global-options] %s' % to_cli(cmd.name)
+        yield 'Usage: %%prog [global-options] %s' % cmd.cli_name()
         for arg in cmd.args():
             name = self.__get_arg_name(arg)
             if name is None:
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index 2ca3aaea82ea63702052eedbd7e4081f239cbaed..47cf318dc90e82f71b34ab4790d12bedbc9ed2ec 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -225,6 +225,15 @@ class HasParam(Plugin):
     # HasParam is the base class for most frontend plugins, that make it to users
     # This flag indicates that the command should not be available in the cli
     NO_CLI = False
+    CLI_NAME = None
+
+    @classmethod
+    def cli_name(cls):
+        if cls.CLI_NAME:
+            return cls.CLI_NAME
+
+        # TODO: replace with to_cli(cls.__name__)
+        return cls.__name__.replace('_', '-')
 
     def _get_param_iterable(self, name, verb='takes'):
         """
@@ -457,6 +466,16 @@ class Command(HasParam):
             self.validate_output(ret, options['version'])
         return ret
 
+    def find_command(self, cli_name):
+        # TODO: replace loop with a dict to map CLI names to commands
+        for name in self.Command:
+            cmd = self.Command[name]
+            if cmd.NO_CLI:
+                continue
+            if cmd.cli_name() == cli_name:
+                return cmd
+        return None
+
     def soft_validate(self, values):
         errors = dict()
         for p in self.params():
-- 
2.4.3



More information about the Freeipa-devel mailing list