[PATCH 5 of 5] extensions: reject any unicode strings in tables before loading

Yuya Nishihara yuya at tcha.org
Sat Feb 17 05:07:40 EST 2018


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1518855869 -32400
#      Sat Feb 17 17:24:29 2018 +0900
# Node ID 5fef8aefa687fc61e62f0fd0decc7a9158150d3f
# Parent  320a41b6eba2532ffbcf2aaa50ec73ecb00f06d4
extensions: reject any unicode strings in tables before loading

This allows us to test hg on Python 3 without disabling third-party
extensions which could pollute cmdtable for example.

diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -122,6 +122,18 @@ def _reportimporterror(ui, err, failed, 
     if ui.debugflag:
         ui.traceback()
 
+def _rejectunicode(name, xs):
+    if isinstance(xs, (list, set, tuple)):
+        for x in xs:
+            _rejectunicode(name, x)
+    elif isinstance(xs, dict):
+        for k, v in xs.items():
+            _rejectunicode(name, k)
+            _rejectunicode(b'%s.%s' % (name, util.forcebytestr(k)), v)
+    elif isinstance(xs, type(u'')):
+        raise error.ProgrammingError(b"unicode %r found in %s" % (xs, name),
+                                     hint="use b'' to make it byte string")
+
 # attributes set by registrar.command
 _cmdfuncattrs = ('norepo', 'optionalrepo', 'inferrepo')
 
@@ -134,19 +146,22 @@ def _validatecmdtable(ui, cmdtable):
                           "registrar.command to register '%s'" % c, '4.6')
         missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)]
         if not missing:
-            for option in e[1]:
-                default = option[2]
-                if isinstance(default, type(u'')):
-                    raise error.ProgrammingError(
-                        "option '%s.%s' has a unicode default value"
-                        % (c, option[1]),
-                        hint=("change the %s.%s default value to a "
-                              "non-unicode string" % (c, option[1])))
             continue
         raise error.ProgrammingError(
             'missing attributes: %s' % ', '.join(missing),
             hint="use @command decorator to register '%s'" % c)
 
+def _validatetables(ui, mod):
+    """Sanity check for loadable tables provided by extension module"""
+    for t in ['cmdtable', 'colortable', 'configtable']:
+        _rejectunicode(t, getattr(mod, t, {}))
+    for t in ['filesetpredicate', 'internalmerge', 'revsetpredicate',
+              'templatefilter', 'templatefunc', 'templatekeyword']:
+        o = getattr(mod, t, None)
+        if o:
+            _rejectunicode(t, o._table)
+    _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
+
 def load(ui, name, path):
     if name.startswith('hgext.') or name.startswith('hgext/'):
         shortname = name[6:]
@@ -168,7 +183,7 @@ def load(ui, name, path):
         ui.warn(_('(third party extension %s requires version %s or newer '
                   'of Mercurial; disabling)\n') % (shortname, minver))
         return
-    _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
+    _validatetables(ui, mod)
 
     _extensions[shortname] = mod
     _order.append(shortname)
diff --git a/tests/test-extension.t b/tests/test-extension.t
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -1707,8 +1707,8 @@ Prohibit the use of unicode strings as t
   > test_unicode_default_value = $TESTTMP/test_unicode_default_value.py
   > EOF
   $ hg -R $TESTTMP/opt-unicode-default dummy
-  *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: option 'dummy.opt' has a unicode default value
-  *** (change the dummy.opt default value to a non-unicode string)
+  *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode u'value' found in cmdtable.dummy
+  *** (use b'' to make it byte string)
   hg: unknown command 'dummy'
   (did you mean summary?)
   [255]


More information about the Mercurial-devel mailing list