[PATCH 3 of 3] extensions: also search for extension in the 'hgext3rd' package

Pierre-Yves David pierre-yves.david at ens-lyon.org
Fri Mar 11 06:47:05 EST 2016


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1457692208 0
#      Fri Mar 11 10:30:08 2016 +0000
# Node ID 394b75d27c45e4f9409e8185c47229990db72af8
# Parent  22f8428e07e42b110ee72cfe2725f714617686b5
# EXP-Topic hgext3rd
# Available At http://hg.netv6.net/marmoute-wip/mercurial/
#              hg pull http://hg.netv6.net/marmoute-wip/mercurial/ -r 394b75d27c45
extensions: also search for extension in the 'hgext3rd' package

Mercurial extensions are not meant to be normal python package/module. Yet the
lack of an official location to install them means that a lot of them actually
install as root level python package, polluting the global Python package
namespace and risking collision with more legit packages. As we recently
discovered, core python actually support namespace package. A way for multiples
distinct "distribution" to share a common top level package without fear of
installation headache. (Namespace package allow submodule installed in different
location (of the 'sys.path') to be imported properly. So we are fine as long as
extension includes a proper 'hgext3rd.__init__.py' to declare the namespace
package.)

Therefore we introduce a 'hgext3rd' namespace packages and search for extension
in it. We'll then recommend third extensions to install themselves in it.
Strictly speaking we could just get third party extensions to install in 'hgext'
as it is also a namespace package. However, this would make the integration of
formerly third party extensions in the main distribution more complicated as the third
party install would overwrite the file from the main install. Moreover, having an
explicit split between third party and core extensions seems like a good idea.

The name 'hgext3rd' have been picked because it is short and seems explicit enough.
Other alternative I could think of where:

- hgextcontrib
- hgextother
- hgextunofficial

diff --git a/hgext/__init__.py b/hgext3rd/__init__.py
copy from hgext/__init__.py
copy to hgext3rd/__init__.py
--- a/hgext/__init__.py
+++ b/hgext3rd/__init__.py
@@ -1,3 +1,4 @@
+# name space package to host third party extensions
 from __future__ import absolute_import
 import pkgutil
 __path__ = pkgutil.extend_path(__path__, __name__)
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -103,11 +103,15 @@ def load(ui, name, path):
     else:
         try:
             mod = _importh("hgext.%s" % name)
         except ImportError as err:
             _reportimporterror(ui, err, "hgext.%s" % name, name)
-            mod = _importh(name)
+            try:
+                mod = _importh("hgext3rd.%s" % name)
+            except ImportError as err:
+                _reportimporterror(ui, err, "hgext3rd.%s" % name, name)
+                mod = _importh(name)
 
     # Before we do anything with the extension, check against minimum stated
     # compatibility. This gives extension authors a mechanism to have their
     # extensions short circuit when loaded with a known incompatible version
     # of Mercurial.
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -504,11 +504,11 @@ cmdclass = {'build': hgbuild,
             }
 
 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
             'mercurial.pure',
             'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
-            'hgext.largefiles']
+            'hgext.largefiles', 'hgext3rd']
 
 common_depends = ['mercurial/util.h']
 
 osutil_ldflags = []
 
diff --git a/tests/test-bad-extension.t b/tests/test-bad-extension.t
--- a/tests/test-bad-extension.t
+++ b/tests/test-bad-extension.t
@@ -54,10 +54,13 @@ show traceback for ImportError of hgext.
   Traceback (most recent call last):
   Exception: bit bucket overflow
   could not import hgext.badext2 (No module named *badext2): trying badext2 (glob)
   Traceback (most recent call last):
   ImportError: No module named *badext2 (glob)
+  could not import hgext3rd.badext2 (No module named badext2): trying badext2
+  Traceback (most recent call last):
+  ImportError: No module named badext2
   *** failed to import extension badext2: No module named badext2
   Traceback (most recent call last):
   ImportError: No module named badext2
 
 confirm that there's no crash when an extension's documentation is bad


More information about the Mercurial-devel mailing list