Rev 4125: Refactor commands.__get_cmd_object to be default-installed hooks. in http://people.ubuntu.com/~robertc/baz2.0/pending/Commands.hooks

Robert Collins robertc at robertcollins.net
Fri Mar 13 02:08:27 GMT 2009


At http://people.ubuntu.com/~robertc/baz2.0/pending/Commands.hooks

------------------------------------------------------------
revno: 4125
revision-id: robertc at robertcollins.net-20090313020823-jvtmzkbsy9i9xdzx
parent: robertc at robertcollins.net-20090312234509-wr3k7d2ylpm6e4cd
committer: Robert Collins <robertc at robertcollins.net>
branch nick: Commands.hooks
timestamp: Fri 2009-03-13 13:08:23 +1100
message:
  Refactor commands.__get_cmd_object to be default-installed hooks.
=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py	2009-03-12 23:04:45 +0000
+++ b/bzrlib/commands.py	2009-03-13 02:08:23 +0000
@@ -132,20 +132,32 @@
 
 def _builtin_commands():
     import bzrlib.builtins
+    return _scan_module_for_commands(bzrlib.builtins)
+
+
+def _scan_module_for_commands(module):
     r = {}
-    builtins = bzrlib.builtins.__dict__
-    for name in builtins:
+    for name, obj in module.__dict__.iteritems():
         if name.startswith("cmd_"):
             real_name = _unsquish_command_name(name)
-            r[real_name] = builtins[name]
+            r[real_name] = obj
     return r
 
 
+def _list_bzr_commands(names):
+    """Return a list of all the registered commands.
+
+    This searches plugins and the core.
+    """
+    # to eliminate duplicates
+    names.update(builtin_command_names())
+    names.update(plugin_command_names())
+    return names
+
+
 def all_command_names():
     """Return a list of all command names."""
-    # to eliminate duplicates
-    names = set(builtin_command_names())
-    names.update(plugin_command_names())
+    names = set()
     for hook in Command.hooks['list_commands']:
         new_names = hook(names)
         if new_names is None:
@@ -203,11 +215,20 @@
     :return: A Command object instance
     :raises: KeyError if no command is found.
     """
-    # Pre-hook command lookup logic.
-    cmd = __get_cmd_object(cmd_name, plugins_override)
-    # Allow hooks to supply/replace commands:
+    # We want only 'ascii' command names, but the user may have typed
+    # in a Unicode name. In that case, they should just get a
+    # 'command not found' error later.
+    # In the future, we may actually support Unicode command names.
+
+    cmd = None
+    # Get a command
     for hook in Command.hooks['get_command']:
         cmd = hook(cmd, cmd_name)
+        if cmd is not None and not plugins_override:
+            # We've found a non-plugin command, don't permit it to be
+            # overridden.
+            if not cmd.plugin_name():
+                break
     if cmd is None:
         try:
             plugin_metadata, provider = probe_for_provider(cmd_name)
@@ -239,40 +260,42 @@
     raise errors.NoPluginAvailable(cmd_name)
 
 
-def __get_cmd_object(cmd_name, plugins_override):
-    """Worker for get_cmd_object which raises KeyError rather than BzrCommandError."""
-    from bzrlib.externalcommand import ExternalCommand
-
-    # We want only 'ascii' command names, but the user may have typed
-    # in a Unicode name. In that case, they should just get a
-    # 'command not found' error later.
-    # In the future, we may actually support Unicode command names.
-
-    # first look up this command under the specified name
-    if plugins_override:
-        try:
-            return plugin_cmds.get(cmd_name)()
-        except KeyError:
-            pass
+def _get_bzr_command(cmd_or_None, cmd_name):
+    """Get a command from bzr's core."""
     cmds = _get_cmd_dict(plugins_override=False)
     try:
         return cmds[cmd_name]()
     except KeyError:
         pass
-    if plugins_override:
-        for key in plugin_cmds.keys():
-            info = plugin_cmds.get_info(key)
-            if cmd_name in info.aliases:
-                return plugin_cmds.get(key)()
     # look for any command which claims this as an alias
     for real_cmd_name, cmd_class in cmds.iteritems():
         if cmd_name in cmd_class.aliases:
             return cmd_class()
-
+    return cmd_or_None
+
+
+def _get_external_command(cmd_or_None, cmd_name):
+    """Lookup a command that is a shell script."""
+    # Only do external command lookups when no command is found so far.
+    if cmd_or_None is not None:
+        return cmd_or_None
+    from bzrlib.externalcommand import ExternalCommand
     cmd_obj = ExternalCommand.find_command(cmd_name)
     if cmd_obj:
         return cmd_obj
-    return None
+
+
+def _get_plugin_command(cmd_or_None, cmd_name):
+    """Get a command from bzr's plugins."""
+    try:
+        return plugin_cmds.get(cmd_name)()
+    except KeyError:
+        pass
+    for key in plugin_cmds.keys():
+        info = plugin_cmds.get_info(key)
+        if cmd_name in info.aliases:
+            return plugin_cmds.get(key)()
+    return cmd_or_None
 
 
 class Command(object):
@@ -656,6 +679,16 @@
             "to replace it with another (eg plugin supplied) version. "
             "list_commands should return the updated dict of commands.",
             (1, 14), None))
+        # We currently ship default hooks to get builtin and plugin supplied
+        # command names.
+        self.install_named_hook("list_commands", _list_bzr_commands,
+            "bzr commands")
+        self.install_named_hook("get_command", _get_bzr_command,
+            "bzr commands")
+        self.install_named_hook("get_command", _get_plugin_command,
+            "bzr plugin commands")
+        self.install_named_hook("get_command", _get_external_command,
+            "bzr external command lookup")
 
 Command.hooks = CommandHooks()
 




More information about the bazaar-commits mailing list