[PATCH V2] commands: use a class as decorator to build table incrementally
Adrian Buehlmann
adrian at cadifra.com
Wed May 11 17:29:07 CDT 2011
On 2011-05-11 23:55, Matt Mackall wrote:
> On Wed, 2011-05-11 at 23:48 +0200, Adrian Buehlmann wrote:
>> On 2011-05-11 20:34, Adrian Buehlmann wrote:
>>> # HG changeset patch
>>> # User Adrian Buehlmann <adrian at cadifra.com>
>>> # Date 1305097807 -7200
>>> # Node ID 7c9c95bbfb3bab2663f0512867dd9115753caede
>>> # Parent c97d8485b5fa46c94b8afcfab0cde97629ba4086
>>> commands: use a class as decorator to build table incrementally
>>>
>>> this allows to define the table entries near the command function
>>>
>>> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
>>> --- a/mercurial/cmdutil.py
>>> +++ b/mercurial/cmdutil.py
>>> @@ -1251,3 +1251,23 @@
>>> raise util.Abort(_("empty commit message"))
>>>
>>> return text
>>> +
>>> +def command(table):
>>> + '''returns a class bound to table that can be used as a decorator
>>> + for populating that command table'''
>>> +
>>> + class cmd(object):
>>> + '''decorator for populating a command table'''
>>> + def __init__(self, name, options, synopsis=None):
>>> + self.name = name
>>> + self.options = options
>>> + self.synopsis = synopsis
>>> +
>>> + def __call__(self, func):
>>> + if self.synopsis:
>>> + table[self.name] = func, self.options, self.synopsis
>>> + else:
>>> + table[self.name] = func, self.options
>>> + return func
>>> +
>>> + return cmd
>>> diff --git a/mercurial/commands.py b/mercurial/commands.py
>>> --- a/mercurial/commands.py
>>> +++ b/mercurial/commands.py
>>> @@ -10,15 +10,129 @@
>>> from i18n import _, gettext
>>> import os, re, sys, difflib, time, tempfile
>>> import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
>>> -import patch, help, url, encoding, templatekw, discovery
>>> +import patch, help, url, encoding, templatekw, discovery, cmdutil
>>> import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
>> ^^^^^^^
>> Bah. Stupid me. cmdutil is already there.
>>
>> Will resend.
>
> We're having a bit of a discussion on IRC about whether writing the
> decorator as a nested function as a class or a nested function is
> better.
>
> My leaning is that since the methods for these decorator classes are
> always just __init__ and __call__ and will never be more than that, the
> class model is just an obfuscation of the nested function style, rather
> than a useful abstraction in its own right.
>
> But I think the rest of it is fine at this point.
>
Ok. So the winner is: Martin's pattern, but binding it to a table via
another outer function, so it can be reused for extensions:
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1251,3 +1251,15 @@
raise util.Abort(_("empty commit message"))
return text
+
+def command(table):
+ '''returns a function object bound to table which can be used as
+ a decorator for populating table as a command table'''
+
+ def cmd(name, options, synopsis):
+ def decorator(func):
+ table[name] = (func, options, synopsis)
+ return func
+ return decorator
+
+ return cmd
For me internally (in my limited brain), I need the class model for
thinking, but I can map it to the Martin pattern ;-)
Full patch in ~10 hours.
Thanks to all.
More information about the Mercurial-devel
mailing list