Overriding commands in plugins

Matt Nordhoff mnordhoff at mattnordhoff.com
Mon Mar 8 15:34:52 GMT 2010


Michael Gliwinski wrote:
> Hi all,
> 
> What is the best/proper/right/working way to override some functionality of a 
> command in a plugin?
> 
> Let's say for example that I want to change 'switch' to print a nice message 
> before it goes on doing its work :)
> 
> From looking at some of the examples I did:
> 
> class cmd_switch(bzrlib.builtins.cmd_switch):
>     __doc__ = bzrlib.builtins.cmd_switch.__doc__
>     def run(**kwargs):
>         self.outf.write('Hello World!'\n)
>         super(cmd_switch, self).run(**kwargs)
> 
> but it seems to me that doesn't take into account the fact that switch may be 
> overriden by other plugins.  So it seems the result of that may be a bit 
> random, depending on which plugin is loaded first?
> 
> Then I also saw this done in the loom plugin:
> 
> class cmd_switch(bzrlib.builtins.cmd_switch):
>     def run_argv_aliases(self, argv, alias_argv=None):
>         try:
>             super(cmd_switch, self).run_argv_aliases(list(argv), alias_argv)
>         except (errors.MustUseDecorated, errors.BzrOptionsError):
>             if self._original_command is None:
>                 raise
>             self._original_command().run_argv_aliases(argv, alias_argv)
> 
> so, IIUC this uses the original command (returned by 
> bzrlib.commands.plugin_cmds.register) stored in _original_command attribute, 
> tries to run the overriden command and in case of problems falls back to 
> original command, yes?
> 
> Is this the more "proper" way?  Does it have to be done in run_argv_aliases?  
> I.e. if I'm only adding certain functionality it would be bit more convenient 
> to do it in run.
> 
> I'll try to update http://doc.bazaar.canonical.com/plugins/en/plugin-
> development.html#extending-an-existing-command if I can figure out something 
> solid to add there.
> 
> Thanks,
> Michael

I know of another way, using bzrlib.commands.get_command_object(), and I
/think/ it's the best way. As an example, this is what Loggerhead does:

        import bzrlib.builtins
        from bzrlib.commands import get_cmd_object, register_command
        from bzrlib.option import Option

        _original_command = get_cmd_object('serve')

        class cmd_serve(bzrlib.builtins.cmd_serve):
            __doc__ = _original_command.__doc__

            takes_options = _original_command.takes_options + [
                Option('http', help=HELP)]

            def run(self, *args, **kw):
                if 'http' in kw:
                    # ... snip ...
                else:
                    super(cmd_serve, self).run(*args, **kw)

<http://bazaar.launchpad.net/~loggerhead-team/loggerhead/trunk-rich/annotate/head%3A/__init__.py#L91>
(<http://xrl.us/bgxved>)
-- 
Matt Nordhoff



More information about the bazaar mailing list