# HG changeset patch # User Christophe de Vienne # Date 2017-08-29 16:24:51 # Node ID 0e0ac8f090483cd5f6cbd93a71f928edeb6c7d70 # Parent b2c691d75d933a52d404399faee64e44237533a6 extensions: prohibit unicode defaults If the default value of an option is a unicode string (something than happen easily when using a 'from __future__ import unicode_literals'), any value passed on the command line will be ignored because the fancyopts module only checks for byte strings and not unicode strings. Changing fancyopts behavior is easy but would make assumptions on how the python3 port should be done, which is outside the scope of this patch. The chosen approach is to stop an extension from being loaded when a unicode default value is detected, with a hint for the developer. diff --git a/mercurial/extensions.py b/mercurial/extensions.py --- a/mercurial/extensions.py +++ b/mercurial/extensions.py @@ -133,6 +133,14 @@ 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), diff --git a/tests/test-extension.t b/tests/test-extension.t --- a/tests/test-extension.t +++ b/tests/test-extension.t @@ -1709,3 +1709,26 @@ Show deprecation warning for the use of $ hg --config extensions.nonregistrar=`pwd`/nonregistrar.py version > /dev/null devel-warn: cmdutil.command is deprecated, use registrar.command to register 'foo' (compatibility will be dropped after Mercurial-4.6, update your code.) * (glob) + +Prohibit the use of unicode strings as the default value of options + + $ hg init $TESTTMP/opt-unicode-default + + $ cat > $TESTTMP/test_unicode_default_value.py << EOF + > from mercurial import registrar + > cmdtable = {} + > command = registrar.command(cmdtable) + > @command('dummy', [('', 'opt', u'value', u'help')], 'ext [OPTIONS]') + > def ext(*args, **opts): + > print(opts['opt']) + > EOF + $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF + > [extensions] + > 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) + hg: unknown command 'dummy' + (did you mean summary?) + [255]