A possible clever trick for extension writing

Greg Ward greg at gerg.ca
Sun Nov 27 10:49:07 CST 2011


On Sat, Nov 26, 2011 at 9:17 PM, I wrote:
> A common pattern in Mercurial extensions is the "dynamic subclass"
> trick. E.g. here is the world's simplest extension using that trick:
[...]
> But of course, this doesn't solve the *real* problem. The *real*
> problem is that I first heard about metaclasses in 1998, back when Jim
> Fulton was still trying convince people there was a problem with
> Python's type system. Ever since Python 2.2 came out I've been looking
> for an excuse to write a metaclass. I may have finally found my
> excuse: Mercurial extensions.

Hahaha never mind. Metaclasses are *still* a solution looking for
problems. This problem is solvable with that good-old fashioned
workhorse of code refactoring, the subroutine:

"""
def makesubclass(repo, name, classtemplate):
    '''Make a new repository subclass and insert it into the class
    hierarchy of repo, dynamically changing the type of
    repo. classtemplate is an object whose __dict__ attribute will be
    used as source of attributes for the new subclass: typically it's
    a "classic" class that just provides instance methods, some of
    which override methods of localrepository.'''
    newclass = type(name,
                    (repo.__class__,),
                    classtemplate.__dict__)
    repo.__class__ = newclass

def reposetup(ui, repo):
    makesubclass(repo, 'simplerepo', simplerepo_template)
"""

The idea is:

  * add makesubclass() to mercurial/extensions.py
  * modify existing extensions (e.g. mq, largefiles, ...):
    - pull the localrepository subclass up to module scope
    - change references to 'ui' (closure dependent) to 'self.ui'
    - make reposetup call makesubclass()

Benefits:
  * less indented code
  * a common bit of magic is factored out to extensions.py

Drawback: the "template" class that implements a lot of essential
extension logic isn't a real class (it's never instantiated or
subclassed) -- it's just a namespace created with the convenient
"class" syntax. The real class is hidden away behind the scenes.

Greg


More information about the Mercurial-devel mailing list