Rev 4003: (robertc) Add a new hook Commands['extend_command'] for plugins that in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Feb 12 04:37:05 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4003
revision-id: pqm at pqm.ubuntu.com-20090212043701-kh62kseozbbcaypb
parent: pqm at pqm.ubuntu.com-20090212024000-dvdhpm2mela5h6f7
parent: robertc at robertcollins.net-20090212034555-qkepf7soohs34erb
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-02-12 04:37:01 +0000
message:
(robertc) Add a new hook Commands['extend_command'] for plugins that
want to alter commands without overriding the entire command.
(Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_commands.py test_command.py-20051019190109-3b17be0f52eaa7a8
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
------------------------------------------------------------
revno: 4000.1.2
revision-id: robertc at robertcollins.net-20090212034555-qkepf7soohs34erb
parent: robertc at robertcollins.net-20090211124950-70c4aa2a8ub65d0s
committer: Robert Collins <robertc at robertcollins.net>
branch nick: extend_command
timestamp: Thu 2009-02-12 14:45:55 +1100
message:
Fix typo in extend_command hook docs.
modified:
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
------------------------------------------------------------
revno: 4000.1.1
revision-id: robertc at robertcollins.net-20090211124950-70c4aa2a8ub65d0s
parent: pqm at pqm.ubuntu.com-20090211011240-gv0zdxmwomt3ndtn
committer: Robert Collins <robertc at robertcollins.net>
branch nick: extend_command
timestamp: Wed 2009-02-11 23:49:50 +1100
message:
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_commands.py test_command.py-20051019190109-3b17be0f52eaa7a8
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
=== modified file 'NEWS'
--- a/NEWS 2009-02-11 00:29:57 +0000
+++ b/NEWS 2009-02-11 12:49:50 +0000
@@ -37,6 +37,10 @@
INTERNALS:
+ * New hook Commands['extend_command'] to allow plugins to access a
+ command object before the command is run (or help generated from
+ it), without overriding the command. (Robert Collins)
+
bzr 1.12rc1 "1234567890" 2009-02-10
-----------------------------------
=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py 2009-02-04 04:10:14 +0000
+++ b/bzrlib/commands.py 2009-02-12 03:45:55 +0000
@@ -50,6 +50,7 @@
from bzrlib import registry
# Compatibility
+from bzrlib.hooks import Hooks
from bzrlib.option import Option
@@ -170,7 +171,11 @@
If true, plugin commands can override builtins.
"""
try:
- return _get_cmd_object(cmd_name, plugins_override)
+ cmd = _get_cmd_object(cmd_name, plugins_override)
+ # Allow plugins to extend commands
+ for hook in Command.hooks['extend_command']:
+ hook(cmd)
+ return cmd
except KeyError:
raise errors.BzrCommandError('unknown command "%s"' % cmd_name)
@@ -216,9 +221,8 @@
except errors.NoPluginAvailable:
pass
else:
- raise errors.CommandAvailableInPlugin(cmd_name,
+ raise errors.CommandAvailableInPlugin(cmd_name,
plugin_metadata, provider)
-
raise KeyError
@@ -279,6 +283,7 @@
sys.stdout is forced to be a binary stream, and line-endings
will not mangled.
+ :cvar hooks: An instance of CommandHooks.
"""
aliases = []
takes_args = []
@@ -573,6 +578,25 @@
return None
+class CommandHooks(Hooks):
+ """Hooks related to Command object creation/enumeration."""
+
+ def __init__(self):
+ """Create the default hooks.
+
+ These are all empty initially, because by default nothing should get
+ notified.
+ """
+ Hooks.__init__(self)
+ # Introduced in 1.13:
+ # invoked after creating a command object to allow modifications such
+ # as adding or removing options, docs etc. Invoked with the command
+ # object.
+ self['extend_command'] = []
+
+Command.hooks = CommandHooks()
+
+
def parse_args(command, argv, alias_argv=None):
"""Parse command line.
@@ -846,6 +870,7 @@
# --verbose in their own way.
option._verbosity_level = saved_verbosity_level
+
def display_command(func):
"""Decorator that suppresses pipe/interrupt errors."""
def ignore_pipe(*args, **kwargs):
=== modified file 'bzrlib/help_topics/en/hooks.txt'
--- a/bzrlib/help_topics/en/hooks.txt 2008-11-11 00:46:06 +0000
+++ b/bzrlib/help_topics/en/hooks.txt 2009-02-11 12:49:50 +0000
@@ -278,3 +278,14 @@
The hook should return a new commit message template.
(New in 1.10.)
+
+extend_command (Commands)
+-------------------------
+
+Invoked by the command line interface when constructing a command object, this
+hook permits the object to be altered after construction - for instance, to add
+options, hook into callbacks that that command offers or more.
+
+The hook signature is hook(cmd) -> None.
+
+This hook was added in 1.13.
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2009-02-11 09:45:27 +0000
+++ b/bzrlib/tests/__init__.py 2009-02-12 04:37:01 +0000
@@ -808,12 +808,14 @@
bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
bzrlib.smart.client._SmartClient: bzrlib.smart.client._SmartClient.hooks,
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
+ bzrlib.commands.Command: bzrlib.commands.Command.hooks,
}
self.addCleanup(self._restoreHooks)
# reset all hooks to an empty instance of the appropriate type
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
bzrlib.smart.client._SmartClient.hooks = bzrlib.smart.client.SmartClientHooks()
bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
+ bzrlib.commands.Command.hooks = bzrlib.commands.CommandHooks()
def _silenceUI(self):
"""Turn off UI for duration of test"""
=== modified file 'bzrlib/tests/test_commands.py'
--- a/bzrlib/tests/test_commands.py 2008-10-21 20:43:05 +0000
+++ b/bzrlib/tests/test_commands.py 2009-02-11 12:49:50 +0000
@@ -19,6 +19,7 @@
import sys
from bzrlib import (
+ builtins,
commands,
config,
errors,
@@ -175,3 +176,45 @@
self.addCleanup(self.remove_fake)
fake_instance = commands.get_cmd_object('fake_alias')
self.assertIsFakeCommand(fake_instance)
+
+
+class TestExtendCommandHook(tests.TestCase):
+
+ def test_fires_on_get_cmd_object(self):
+ # The extend_command(cmd) hook fires when commands are delivered to the
+ # ui, not simply at registration (because lazy registered plugin
+ # commands are registered).
+ # when they are simply created.
+ hook_calls = []
+ commands.Command.hooks.install_named_hook(
+ "extend_command", hook_calls.append, None)
+ # create a command, should not fire
+ class ACommand(commands.Command):
+ """A sample command."""
+ cmd = ACommand()
+ self.assertEqual([], hook_calls)
+ # -- as a builtin
+ # register the command class, should not fire
+ try:
+ builtins.cmd_test_extend_command_hook = ACommand
+ self.assertEqual([], hook_calls)
+ # and ask for the object, should fire
+ cmd = commands.get_cmd_object('test-extend-command-hook')
+ # For resilience - to ensure all code paths hit it - we
+ # fire on everything returned in the 'cmd_dict', which is currently
+ # all known commands, so assert that cmd is in hook_calls
+ self.assertSubset([cmd], hook_calls)
+ del hook_calls[:]
+ finally:
+ del builtins.cmd_test_extend_command_hook
+ # -- as a plugin lazy registration
+ try:
+ # register the command class, should not fire
+ commands.plugin_cmds.register_lazy('cmd_fake', [],
+ 'bzrlib.tests.fake_command')
+ self.assertEqual([], hook_calls)
+ # and ask for the object, should fire
+ cmd = commands.get_cmd_object('fake')
+ self.assertEqual([cmd], hook_calls)
+ finally:
+ commands.plugin_cmds.remove('fake')
=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py 2009-01-08 16:57:10 +0000
+++ b/bzrlib/tests/test_selftest.py 2009-02-11 12:49:50 +0000
@@ -1444,10 +1444,15 @@
def test_hooks_sanitised(self):
"""The bzrlib hooks should be sanitised by setUp."""
+ # Note this test won't fail with hooks that the core library doesn't
+ # use - but it trigger with a plugin that adds hooks, so its still a
+ # useful warning in that case.
self.assertEqual(bzrlib.branch.BranchHooks(),
bzrlib.branch.Branch.hooks)
self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
bzrlib.smart.server.SmartTCPServer.hooks)
+ self.assertEqual(bzrlib.commands.CommandHooks(),
+ bzrlib.commands.Command.hooks)
def test__gather_lsprof_in_benchmarks(self):
"""When _gather_lsprof_in_benchmarks is on, accumulate profile data.
More information about the bazaar-commits
mailing list