[PATCH 0 of 1] debugcommands.py

Adrian Buehlmann adrian at cadifra.com
Wed May 11 04:44:00 CDT 2011


On 2011-05-11 10:09, Martin Geisler wrote:
> Adrian Buehlmann <adrian at cadifra.com> writes:
> 
>> On 2011-05-10 22:28, Matt Mackall wrote:
>>> One of the few things I would consider changing here is the commands
>>> table. Ideally the command table entries would somehow be stored right
>>> next to the command definition.
>>
>> Example:
>>
>> <snip>
>>
>> table = {}
>>
>> ...
>>
>> def init(ui, dest=".", **opts):
>>     """create a new repository in the given directory
>>
>>     Initialize a new repository in the given directory. If the given
>>     directory does not exist, it will be created.
>>
>>     If no directory is given, the current directory is used.
>>
>>     It is possible to specify an ``ssh://`` URL as the destination.
>>     See :hg:`help urls` for more information.
>>
>>     Returns 0 on success.
>>     """
>>     hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
>>
>> table["^init"] = (init,
>>     remoteopts,
>>     _('[-e CMD] [--remotecmd CMD] [DEST]'))
>>
>> </snip>
>>
>> would that be acceptable?
> 
> I think a decorator would be nicer:
> 
>   @command(name="^init",
>            options=remoteopts,
>            synopsis=_('[-e CMD] [--remotecmd CMD] [DEST]'))
>   def init(ui, dest=".", **opts):
>       ...
> 
> But as Benoit mentioned, this might impact the startup time negatively.
> The decorator would have to do something like this:
> 
>   def command(name, options, synopsis):
>       def decorator(func):
>           table[name] = (func, options, synopsis)
>           return func
>       return decorator
> 
> which means that we get two extra function calls for every defined
> command.
> 

Thanks for the hint. Amazing stuff these decorators!

Or (after having pondered http://www.artima.com/weblogs/viewpost.jsp?thread=240845 ):

table = {}

class command(object):
    def __init__(self, name, options, synopsis):
        self.name = name
        self.options = options
        self.synopsis = synopsis

    def __call__(self, func):
        table[self.name] = (func, self.options, self.synopsis)

...

@command('^log|history',
    [('f', 'follow', None,
     _('follow changeset history,'
       ' or file history across copies and renames')),
    ('', 'follow-first', None,
     _('only follow the first parent of merge changesets')),
    ('d', 'date', '',
     _('show revisions matching date spec'), _('DATE')),
    ('C', 'copies', None, _('show copied files')),
    ('k', 'keyword', [],
     _('do case-insensitive search for a given text'), _('TEXT')),
    ('r', 'rev', [],
     _('show the specified revision or range'), _('REV')),
    ('', 'removed', None, _('include revisions where files were removed')),
    ('m', 'only-merges', None, _('show only merges')),
    ('u', 'user', [],
     _('revisions committed by user'), _('USER')),
    ('', 'only-branch', [],
     _('show only changesets within the given named branch (DEPRECATED)'),
     _('BRANCH')),
    ('b', 'branch', [],
     _('show changesets within the given named branch'), _('BRANCH')),
    ('P', 'prune', [],
     _('do not display revision or any of its ancestors'), _('REV')),
    ] + logopts + walkopts,
    _('[OPTION]... [FILE]')
)
def log(ui, repo, *pats, **opts):
    ...

I think I'll do a full patch for this and then we can measure how fast
(or slow) it is. The increased beauty of the code might be worth it.



More information about the Mercurial-devel mailing list