eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/extensions.py
changeset 69 c6bca38c1cbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/extensions.py	Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,302 @@
+# extensions.py - extension handling for mercurial
+#
+# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+import imp, os
+import util, cmdutil, help, error
+from i18n import _, gettext
+
+_extensions = {}
+_order = []
+
+def extensions():
+    for name in _order:
+        module = _extensions[name]
+        if module:
+            yield name, module
+
+def find(name):
+    '''return module with given extension name'''
+    try:
+        return _extensions[name]
+    except KeyError:
+        for k, v in _extensions.iteritems():
+            if k.endswith('.' + name) or k.endswith('/' + name):
+                return v
+        raise KeyError(name)
+
+def loadpath(path, module_name):
+    module_name = module_name.replace('.', '_')
+    path = util.expandpath(path)
+    if os.path.isdir(path):
+        # module/__init__.py style
+        d, f = os.path.split(path.rstrip('/'))
+        fd, fpath, desc = imp.find_module(f, [d])
+        return imp.load_module(module_name, fd, fpath, desc)
+    else:
+        return imp.load_source(module_name, path)
+
+def load(ui, name, path):
+    # unused ui argument kept for backwards compatibility
+    if name.startswith('hgext.') or name.startswith('hgext/'):
+        shortname = name[6:]
+    else:
+        shortname = name
+    if shortname in _extensions:
+        return _extensions[shortname]
+    _extensions[shortname] = None
+    if path:
+        # the module will be loaded in sys.modules
+        # choose an unique name so that it doesn't
+        # conflicts with other modules
+        mod = loadpath(path, 'hgext.%s' % name)
+    else:
+        def importh(name):
+            mod = __import__(name)
+            components = name.split('.')
+            for comp in components[1:]:
+                mod = getattr(mod, comp)
+            return mod
+        try:
+            mod = importh("hgext.%s" % name)
+        except ImportError:
+            mod = importh(name)
+    _extensions[shortname] = mod
+    _order.append(shortname)
+    return mod
+
+def loadall(ui):
+    result = ui.configitems("extensions")
+    newindex = len(_order)
+    for (name, path) in result:
+        if path:
+            if path[0] == '!':
+                continue
+        try:
+            load(ui, name, path)
+        except KeyboardInterrupt:
+            raise
+        except Exception, inst:
+            if path:
+                ui.warn(_("*** failed to import extension %s from %s: %s\n")
+                        % (name, path, inst))
+            else:
+                ui.warn(_("*** failed to import extension %s: %s\n")
+                        % (name, inst))
+            if ui.traceback():
+                return 1
+
+    for name in _order[newindex:]:
+        uisetup = getattr(_extensions[name], 'uisetup', None)
+        if uisetup:
+            uisetup(ui)
+
+    for name in _order[newindex:]:
+        extsetup = getattr(_extensions[name], 'extsetup', None)
+        if extsetup:
+            try:
+                extsetup(ui)
+            except TypeError:
+                if extsetup.func_code.co_argcount != 0:
+                    raise
+                extsetup() # old extsetup with no ui argument
+
+def wrapcommand(table, command, wrapper):
+    '''Wrap the command named `command' in table
+
+    Replace command in the command table with wrapper. The wrapped command will
+    be inserted into the command table specified by the table argument.
+
+    The wrapper will be called like
+
+      wrapper(orig, *args, **kwargs)
+
+    where orig is the original (wrapped) function, and *args, **kwargs
+    are the arguments passed to it.
+    '''
+    assert hasattr(wrapper, '__call__')
+    aliases, entry = cmdutil.findcmd(command, table)
+    for alias, e in table.iteritems():
+        if e is entry:
+            key = alias
+            break
+
+    origfn = entry[0]
+    def wrap(*args, **kwargs):
+        return util.checksignature(wrapper)(
+            util.checksignature(origfn), *args, **kwargs)
+
+    wrap.__doc__ = getattr(origfn, '__doc__')
+    wrap.__module__ = getattr(origfn, '__module__')
+
+    newentry = list(entry)
+    newentry[0] = wrap
+    table[key] = tuple(newentry)
+    return entry
+
+def wrapfunction(container, funcname, wrapper):
+    '''Wrap the function named funcname in container
+
+    Replace the funcname member in the given container with the specified
+    wrapper. The container is typically a module, class, or instance.
+
+    The wrapper will be called like
+
+      wrapper(orig, *args, **kwargs)
+
+    where orig is the original (wrapped) function, and *args, **kwargs
+    are the arguments passed to it.
+
+    Wrapping methods of the repository object is not recommended since
+    it conflicts with extensions that extend the repository by
+    subclassing. All extensions that need to extend methods of
+    localrepository should use this subclassing trick: namely,
+    reposetup() should look like
+
+      def reposetup(ui, repo):
+          class myrepo(repo.__class__):
+              def whatever(self, *args, **kwargs):
+                  [...extension stuff...]
+                  super(myrepo, self).whatever(*args, **kwargs)
+                  [...extension stuff...]
+
+          repo.__class__ = myrepo
+
+    In general, combining wrapfunction() with subclassing does not
+    work. Since you cannot control what other extensions are loaded by
+    your end users, you should play nicely with others by using the
+    subclass trick.
+    '''
+    assert hasattr(wrapper, '__call__')
+    def wrap(*args, **kwargs):
+        return wrapper(origfn, *args, **kwargs)
+
+    origfn = getattr(container, funcname)
+    assert hasattr(origfn, '__call__')
+    setattr(container, funcname, wrap)
+    return origfn
+
+def _disabledpaths(strip_init=False):
+    '''find paths of disabled extensions. returns a dict of {name: path}
+    removes /__init__.py from packages if strip_init is True'''
+    import hgext
+    extpath = os.path.dirname(os.path.abspath(hgext.__file__))
+    try: # might not be a filesystem path
+        files = os.listdir(extpath)
+    except OSError:
+        return {}
+
+    exts = {}
+    for e in files:
+        if e.endswith('.py'):
+            name = e.rsplit('.', 1)[0]
+            path = os.path.join(extpath, e)
+        else:
+            name = e
+            path = os.path.join(extpath, e, '__init__.py')
+            if not os.path.exists(path):
+                continue
+            if strip_init:
+                path = os.path.dirname(path)
+        if name in exts or name in _order or name == '__init__':
+            continue
+        exts[name] = path
+    return exts
+
+def _disabledhelp(path):
+    '''retrieve help synopsis of a disabled extension (without importing)'''
+    try:
+        file = open(path)
+    except IOError:
+        return
+    else:
+        doc = help.moduledoc(file)
+        file.close()
+
+    if doc: # extracting localized synopsis
+        return gettext(doc).splitlines()[0]
+    else:
+        return _('(no help text available)')
+
+def disabled():
+    '''find disabled extensions from hgext
+    returns a dict of {name: desc}, and the max name length'''
+
+    paths = _disabledpaths()
+    if not paths:
+        return None, 0
+
+    exts = {}
+    maxlength = 0
+    for name, path in paths.iteritems():
+        doc = _disabledhelp(path)
+        if not doc:
+            continue
+
+        exts[name] = doc
+        if len(name) > maxlength:
+            maxlength = len(name)
+
+    return exts, maxlength
+
+def disabledext(name):
+    '''find a specific disabled extension from hgext. returns desc'''
+    paths = _disabledpaths()
+    if name in paths:
+        return _disabledhelp(paths[name])
+
+def disabledcmd(cmd, strict=False):
+    '''import disabled extensions until cmd is found.
+    returns (cmdname, extname, doc)'''
+
+    paths = _disabledpaths(strip_init=True)
+    if not paths:
+        raise error.UnknownCommand(cmd)
+
+    def findcmd(cmd, name, path):
+        try:
+            mod = loadpath(path, 'hgext.%s' % name)
+        except Exception:
+            return
+        try:
+            aliases, entry = cmdutil.findcmd(cmd,
+                getattr(mod, 'cmdtable', {}), strict)
+        except (error.AmbiguousCommand, error.UnknownCommand):
+            return
+        for c in aliases:
+            if c.startswith(cmd):
+                cmd = c
+                break
+        else:
+            cmd = aliases[0]
+        return (cmd, name, mod)
+
+    # first, search for an extension with the same name as the command
+    path = paths.pop(cmd, None)
+    if path:
+        ext = findcmd(cmd, cmd, path)
+        if ext:
+            return ext
+
+    # otherwise, interrogate each extension until there's a match
+    for name, path in paths.iteritems():
+        ext = findcmd(cmd, name, path)
+        if ext:
+            return ext
+
+    raise error.UnknownCommand(cmd)
+
+def enabled():
+    '''return a dict of {name: desc} of extensions, and the max name length'''
+    exts = {}
+    maxlength = 0
+    for ename, ext in extensions():
+        doc = (gettext(ext.__doc__) or _('(no help text available)'))
+        ename = ename.split('.')[-1]
+        maxlength = max(len(ename), maxlength)
+        exts[ename] = doc.splitlines()[0].strip()
+
+    return exts, maxlength