| Index: third_party/logilab/common/configuration.py | 
| diff --git a/third_party/logilab/common/configuration.py b/third_party/logilab/common/configuration.py | 
| index 1371c76d3bb5711a493e40c417200f70d8f49583..0eafa10a07da917e074e49b34630b94545082d8f 100644 | 
| --- a/third_party/logilab/common/configuration.py | 
| +++ b/third_party/logilab/common/configuration.py | 
| @@ -1,4 +1,4 @@ | 
| -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 
| +# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 
| # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 
| # | 
| # This file is part of logilab-common. | 
| @@ -96,19 +96,8 @@ Quick start: simplest usage | 
| multiple=4,5,6 | 
|  | 
| number=3 | 
| - | 
| -  Note : starting with Python 2.7 ConfigParser is able to take into | 
| -  account the order of occurrences of the options into a file (by | 
| -  using an OrderedDict). If you have two options changing some common | 
| -  state, like a 'disable-all-stuff' and a 'enable-some-stuff-a', their | 
| -  order of appearance will be significant : the last specified in the | 
| -  file wins. For earlier version of python and logilab.common newer | 
| -  than 0.61 the behaviour is unspecified. | 
| - | 
| +  >>> | 
| """ | 
| - | 
| -from __future__ import print_function | 
| - | 
| __docformat__ = "restructuredtext en" | 
|  | 
| __all__ = ('OptionsManagerMixIn', 'OptionsProviderMixIn', | 
| @@ -120,17 +109,16 @@ import sys | 
| import re | 
| from os.path import exists, expanduser | 
| from copy import copy | 
| +from ConfigParser import ConfigParser, NoOptionError, NoSectionError, \ | 
| +     DuplicateSectionError | 
| from warnings import warn | 
|  | 
| -from six import string_types | 
| -from six.moves import range, configparser as cp, input | 
| +from logilab.common.compat import callable, raw_input, str_encode as _encode | 
|  | 
| -from logilab.common.compat import str_encode as _encode | 
| -from logilab.common.deprecation import deprecated | 
| from logilab.common.textutils import normalize_text, unquote | 
| -from logilab.common import optik_ext | 
| +from logilab.common import optik_ext as optparse | 
|  | 
| -OptionError = optik_ext.OptionError | 
| +OptionError = optparse.OptionError | 
|  | 
| REQUIRED = [] | 
|  | 
| @@ -148,66 +136,63 @@ def _get_encoding(encoding, stream): | 
|  | 
| # validation functions ######################################################## | 
|  | 
| -# validators will return the validated value or raise optparse.OptionValueError | 
| -# XXX add to documentation | 
| - | 
| def choice_validator(optdict, name, value): | 
| """validate and return a converted value for option of type 'choice' | 
| """ | 
| if not value in optdict['choices']: | 
| msg = "option %s: invalid value: %r, should be in %s" | 
| -        raise optik_ext.OptionValueError(msg % (name, value, optdict['choices'])) | 
| +        raise optparse.OptionValueError(msg % (name, value, optdict['choices'])) | 
| return value | 
|  | 
| def multiple_choice_validator(optdict, name, value): | 
| """validate and return a converted value for option of type 'choice' | 
| """ | 
| choices = optdict['choices'] | 
| -    values = optik_ext.check_csv(None, name, value) | 
| +    values = optparse.check_csv(None, name, value) | 
| for value in values: | 
| if not value in choices: | 
| msg = "option %s: invalid value: %r, should be in %s" | 
| -            raise optik_ext.OptionValueError(msg % (name, value, choices)) | 
| +            raise optparse.OptionValueError(msg % (name, value, choices)) | 
| return values | 
|  | 
| def csv_validator(optdict, name, value): | 
| """validate and return a converted value for option of type 'csv' | 
| """ | 
| -    return optik_ext.check_csv(None, name, value) | 
| +    return optparse.check_csv(None, name, value) | 
|  | 
| def yn_validator(optdict, name, value): | 
| """validate and return a converted value for option of type 'yn' | 
| """ | 
| -    return optik_ext.check_yn(None, name, value) | 
| +    return optparse.check_yn(None, name, value) | 
|  | 
| def named_validator(optdict, name, value): | 
| """validate and return a converted value for option of type 'named' | 
| """ | 
| -    return optik_ext.check_named(None, name, value) | 
| +    return optparse.check_named(None, name, value) | 
|  | 
| def file_validator(optdict, name, value): | 
| """validate and return a filepath for option of type 'file'""" | 
| -    return optik_ext.check_file(None, name, value) | 
| +    return optparse.check_file(None, name, value) | 
|  | 
| def color_validator(optdict, name, value): | 
| """validate and return a valid color for option of type 'color'""" | 
| -    return optik_ext.check_color(None, name, value) | 
| +    return optparse.check_color(None, name, value) | 
|  | 
| def password_validator(optdict, name, value): | 
| """validate and return a string for option of type 'password'""" | 
| -    return optik_ext.check_password(None, name, value) | 
| +    return optparse.check_password(None, name, value) | 
|  | 
| def date_validator(optdict, name, value): | 
| """validate and return a mx DateTime object for option of type 'date'""" | 
| -    return optik_ext.check_date(None, name, value) | 
| +    return optparse.check_date(None, name, value) | 
|  | 
| def time_validator(optdict, name, value): | 
| """validate and return a time object for option of type 'time'""" | 
| -    return optik_ext.check_time(None, name, value) | 
| +    return optparse.check_time(None, name, value) | 
|  | 
| def bytes_validator(optdict, name, value): | 
| """validate and return an integer for option of type 'bytes'""" | 
| -    return optik_ext.check_bytes(None, name, value) | 
| +    return optparse.check_bytes(None, name, value) | 
|  | 
|  | 
| VALIDATORS = {'string': unquote, | 
| @@ -237,18 +222,14 @@ def _call_validator(opttype, optdict, option, value): | 
| except TypeError: | 
| try: | 
| return VALIDATORS[opttype](value) | 
| -        except optik_ext.OptionValueError: | 
| +        except optparse.OptionValueError: | 
| raise | 
| except: | 
| -            raise optik_ext.OptionValueError('%s value (%r) should be of type %s' % | 
| +            raise optparse.OptionValueError('%s value (%r) should be of type %s' % | 
| (option, value, opttype)) | 
|  | 
| # user input functions ######################################################## | 
|  | 
| -# user input functions will ask the user for input on stdin then validate | 
| -# the result and return the validated value or raise optparse.OptionValueError | 
| -# XXX add to documentation | 
| - | 
| def input_password(optdict, question='password:'): | 
| from getpass import getpass | 
| while True: | 
| @@ -256,23 +237,23 @@ def input_password(optdict, question='password:'): | 
| value2 = getpass('confirm: ') | 
| if value == value2: | 
| return value | 
| -        print('password mismatch, try again') | 
| +        print 'password mismatch, try again' | 
|  | 
| def input_string(optdict, question): | 
| -    value = input(question).strip() | 
| +    value = raw_input(question).strip() | 
| return value or None | 
|  | 
| def _make_input_function(opttype): | 
| def input_validator(optdict, question): | 
| while True: | 
| -            value = input(question) | 
| +            value = raw_input(question) | 
| if not value.strip(): | 
| return None | 
| try: | 
| return _call_validator(opttype, optdict, None, value) | 
| -            except optik_ext.OptionValueError as ex: | 
| +            except optparse.OptionValueError, ex: | 
| msg = str(ex).split(':', 1)[-1].strip() | 
| -                print('bad value: %s' % msg) | 
| +                print 'bad value: %s' % msg | 
| return input_validator | 
|  | 
| INPUT_FUNCTIONS = { | 
| @@ -283,8 +264,6 @@ INPUT_FUNCTIONS = { | 
| for opttype in VALIDATORS.keys(): | 
| INPUT_FUNCTIONS.setdefault(opttype, _make_input_function(opttype)) | 
|  | 
| -# utility functions ############################################################ | 
| - | 
| def expand_default(self, option): | 
| """monkey patch OptionParser.expand_default since we have a particular | 
| way to handle defaults to avoid overriding values in the configuration | 
| @@ -299,15 +278,15 @@ def expand_default(self, option): | 
| value = None | 
| else: | 
| optdict = provider.get_option_def(optname) | 
| -        optname = provider.option_attrname(optname, optdict) | 
| +        optname = provider.option_name(optname, optdict) | 
| value = getattr(provider.config, optname, optdict) | 
| value = format_option_value(optdict, value) | 
| -    if value is optik_ext.NO_DEFAULT or not value: | 
| +    if value is optparse.NO_DEFAULT or not value: | 
| value = self.NO_DEFAULT_VALUE | 
| return option.help.replace(self.default_tag, str(value)) | 
|  | 
|  | 
| -def _validate(value, optdict, name=''): | 
| +def convert(value, optdict, name=''): | 
| """return a validated value for an option according to its type | 
|  | 
| optional argument name is only used for error message formatting | 
| @@ -318,9 +297,6 @@ def _validate(value, optdict, name=''): | 
| # FIXME | 
| return value | 
| return _call_validator(_type, optdict, name, value) | 
| -convert = deprecated('[0.60] convert() was renamed _validate()')(_validate) | 
| - | 
| -# format and output functions ################################################## | 
|  | 
| def comment(string): | 
| """return string as a comment""" | 
| @@ -370,7 +346,7 @@ def format_option_value(optdict, value): | 
| value = value.pattern | 
| elif optdict.get('type') == 'yn': | 
| value = value and 'yes' or 'no' | 
| -    elif isinstance(value, string_types) and value.isspace(): | 
| +    elif isinstance(value, (str, unicode)) and value.isspace(): | 
| value = "'%s'" % value | 
| elif optdict.get('type') == 'time' and isinstance(value, (float, int, long)): | 
| value = format_time(value) | 
| @@ -382,8 +358,8 @@ def ini_format_section(stream, section, options, encoding=None, doc=None): | 
| """format an options section using the INI format""" | 
| encoding = _get_encoding(encoding, stream) | 
| if doc: | 
| -        print(_encode(comment(doc), encoding), file=stream) | 
| -    print('[%s]' % section, file=stream) | 
| +        print >> stream, _encode(comment(doc), encoding) | 
| +    print >> stream, '[%s]' % section | 
| ini_format(stream, options, encoding) | 
|  | 
| def ini_format(stream, options, encoding): | 
| @@ -393,20 +369,20 @@ def ini_format(stream, options, encoding): | 
| help = optdict.get('help') | 
| if help: | 
| help = normalize_text(help, line_len=79, indent='# ') | 
| -            print(file=stream) | 
| -            print(_encode(help, encoding), file=stream) | 
| +            print >> stream | 
| +            print >> stream, _encode(help, encoding) | 
| else: | 
| -            print(file=stream) | 
| +            print >> stream | 
| if value is None: | 
| -            print('#%s=' % optname, file=stream) | 
| +            print >> stream, '#%s=' % optname | 
| else: | 
| value = _encode(value, encoding).strip() | 
| -            print('%s=%s' % (optname, value), file=stream) | 
| +            print >> stream, '%s=%s' % (optname, value) | 
|  | 
| format_section = ini_format_section | 
|  | 
| def rest_format_section(stream, section, options, encoding=None, doc=None): | 
| -    """format an options section using as ReST formatted output""" | 
| +    """format an options section using the INI format""" | 
| encoding = _get_encoding(encoding, stream) | 
| if section: | 
| print >> stream, '%s\n%s' % (section, "'"*len(section)) | 
| @@ -425,7 +401,6 @@ def rest_format_section(stream, section, options, encoding=None, doc=None): | 
| print >> stream, '' | 
| print >> stream, '  Default: ``%s``' % value.replace("`` ", "```` ``") | 
|  | 
| -# Options Manager ############################################################## | 
|  | 
| class OptionsManagerMixIn(object): | 
| """MixIn to handle a configuration from both a configuration file and | 
| @@ -448,9 +423,9 @@ class OptionsManagerMixIn(object): | 
|  | 
| def reset_parsers(self, usage='', version=None): | 
| # configuration file parser | 
| -        self.cfgfile_parser = cp.ConfigParser() | 
| +        self.cfgfile_parser = ConfigParser() | 
| # command line parser | 
| -        self.cmdline_parser = optik_ext.OptionParser(usage=usage, version=version) | 
| +        self.cmdline_parser = optparse.OptionParser(usage=usage, version=version) | 
| self.cmdline_parser.options_manager = self | 
| self._optik_option_attrs = set(self.cmdline_parser.option_class.ATTRS) | 
|  | 
| @@ -486,7 +461,7 @@ class OptionsManagerMixIn(object): | 
| if group_name in self._mygroups: | 
| group = self._mygroups[group_name] | 
| else: | 
| -            group = optik_ext.OptionGroup(self.cmdline_parser, | 
| +            group = optparse.OptionGroup(self.cmdline_parser, | 
| title=group_name.capitalize()) | 
| self.cmdline_parser.add_option_group(group) | 
| group.level = provider.level | 
| @@ -522,9 +497,9 @@ class OptionsManagerMixIn(object): | 
| # default is handled here and *must not* be given to optik if you | 
| # want the whole machinery to work | 
| if 'default' in optdict: | 
| -            if ('help' in optdict | 
| -                and optdict.get('default') is not None | 
| -                and not optdict['action'] in ('store_true', 'store_false')): | 
| +            if (optparse.OPTPARSE_FORMAT_DEFAULT and 'help' in optdict and | 
| +                optdict.get('default') is not None and | 
| +                not optdict['action'] in ('store_true', 'store_false')): | 
| optdict['help'] += ' [current: %default]' | 
| del optdict['default'] | 
| args = ['--' + str(opt)] | 
| @@ -533,7 +508,7 @@ class OptionsManagerMixIn(object): | 
| args.append('-' + optdict['short']) | 
| del optdict['short'] | 
| # cleanup option definition dict before giving it to optik | 
| -        for key in list(optdict.keys()): | 
| +        for key in optdict.keys(): | 
| if not key in self._optik_option_attrs: | 
| optdict.pop(key) | 
| return args, optdict | 
| @@ -580,7 +555,7 @@ class OptionsManagerMixIn(object): | 
| printed = False | 
| for section in sections: | 
| if printed: | 
| -                print('\n', file=stream) | 
| +                print >> stream, '\n' | 
| format_section(stream, section.upper(), options_by_section[section], | 
| encoding) | 
| printed = True | 
| @@ -591,7 +566,7 @@ class OptionsManagerMixIn(object): | 
| """ | 
| self._monkeypatch_expand_default() | 
| try: | 
| -            optik_ext.generate_manpage(self.cmdline_parser, pkginfo, | 
| +            optparse.generate_manpage(self.cmdline_parser, pkginfo, | 
| section, stream=stream or sys.stdout, | 
| level=self._maxlevel) | 
| finally: | 
| @@ -619,7 +594,7 @@ class OptionsManagerMixIn(object): | 
| if opt in self._all_options: | 
| break # already processed | 
| def helpfunc(option, opt, val, p, level=helplevel): | 
| -                print(self.help(level)) | 
| +                print self.help(level) | 
| sys.exit(0) | 
| helpmsg = '%s verbose help.' % ' '.join(['more'] * helplevel) | 
| optdict = {'action' : 'callback', 'callback' : helpfunc, | 
| @@ -641,7 +616,7 @@ class OptionsManagerMixIn(object): | 
| parser._sections[sect.upper()] = values | 
| elif not self.quiet: | 
| msg = 'No config file found, using default configuration' | 
| -            print(msg, file=sys.stderr) | 
| +            print >> sys.stderr, msg | 
| return | 
|  | 
| def input_config(self, onlysection=None, inputlevel=0, stream=None): | 
| @@ -667,13 +642,13 @@ class OptionsManagerMixIn(object): | 
| options provider) | 
| """ | 
| parser = self.cfgfile_parser | 
| -        for section in parser.sections(): | 
| -             for option, value in parser.items(section): | 
| -                  try: | 
| -                       self.global_set_option(option, value) | 
| -                  except (KeyError, OptionError): | 
| -                       # TODO handle here undeclared options appearing in the config file | 
| -                       continue | 
| +        for provider in self.options_providers: | 
| +            for section, option, optdict in provider.all_options(): | 
| +                try: | 
| +                    value = parser.get(section, option) | 
| +                    provider.set_option(option, value, optdict=optdict) | 
| +                except (NoSectionError, NoOptionError), ex: | 
| +                    continue | 
|  | 
| def load_configuration(self, **kwargs): | 
| """override configuration according to given parameters | 
| @@ -711,7 +686,7 @@ class OptionsManagerMixIn(object): | 
|  | 
| def add_help_section(self, title, description, level=0): | 
| """add a dummy option section for help purpose """ | 
| -        group = optik_ext.OptionGroup(self.cmdline_parser, | 
| +        group = optparse.OptionGroup(self.cmdline_parser, | 
| title=title.capitalize(), | 
| description=description) | 
| group.level = level | 
| @@ -719,18 +694,18 @@ class OptionsManagerMixIn(object): | 
| self.cmdline_parser.add_option_group(group) | 
|  | 
| def _monkeypatch_expand_default(self): | 
| -        # monkey patch optik_ext to deal with our default values | 
| +        # monkey patch optparse to deal with our default values | 
| try: | 
| -            self.__expand_default_backup = optik_ext.HelpFormatter.expand_default | 
| -            optik_ext.HelpFormatter.expand_default = expand_default | 
| +            self.__expand_default_backup = optparse.HelpFormatter.expand_default | 
| +            optparse.HelpFormatter.expand_default = expand_default | 
| except AttributeError: | 
| # python < 2.4: nothing to be done | 
| pass | 
| def _unmonkeypatch_expand_default(self): | 
| # remove monkey patch | 
| -        if hasattr(optik_ext.HelpFormatter, 'expand_default'): | 
| -            # unpatch optik_ext to avoid side effects | 
| -            optik_ext.HelpFormatter.expand_default = self.__expand_default_backup | 
| +        if hasattr(optparse.HelpFormatter, 'expand_default'): | 
| +            # unpatch optparse to avoid side effects | 
| +            optparse.HelpFormatter.expand_default = self.__expand_default_backup | 
|  | 
| def help(self, level=0): | 
| """return the usage string for available options """ | 
| @@ -759,7 +734,6 @@ class Method(object): | 
| assert self._inst, 'unbound method' | 
| return getattr(self._inst, self.method)(*args, **kwargs) | 
|  | 
| -# Options Provider ############################################################# | 
|  | 
| class OptionsProviderMixIn(object): | 
| """Mixin to provide options to an OptionsManager""" | 
| @@ -771,7 +745,7 @@ class OptionsProviderMixIn(object): | 
| level = 0 | 
|  | 
| def __init__(self): | 
| -        self.config = optik_ext.Values() | 
| +        self.config = optparse.Values() | 
| for option in self.options: | 
| try: | 
| option, optdict = option | 
| @@ -803,41 +777,41 @@ class OptionsProviderMixIn(object): | 
| default = default() | 
| return default | 
|  | 
| -    def option_attrname(self, opt, optdict=None): | 
| +    def option_name(self, opt, optdict=None): | 
| """get the config attribute corresponding to opt | 
| """ | 
| if optdict is None: | 
| optdict = self.get_option_def(opt) | 
| return optdict.get('dest', opt.replace('-', '_')) | 
| -    option_name = deprecated('[0.60] OptionsProviderMixIn.option_name() was renamed to option_attrname()')(option_attrname) | 
|  | 
| def option_value(self, opt): | 
| """get the current value for the given option""" | 
| -        return getattr(self.config, self.option_attrname(opt), None) | 
| +        return getattr(self.config, self.option_name(opt), None) | 
|  | 
| def set_option(self, opt, value, action=None, optdict=None): | 
| """method called to set an option (registered in the options list) | 
| """ | 
| +        # print "************ setting option", opt," to value", value | 
| if optdict is None: | 
| optdict = self.get_option_def(opt) | 
| if value is not None: | 
| -            value = _validate(value, optdict, opt) | 
| +            value = convert(value, optdict, opt) | 
| if action is None: | 
| action = optdict.get('action', 'store') | 
| if optdict.get('type') == 'named': # XXX need specific handling | 
| -            optname = self.option_attrname(opt, optdict) | 
| +            optname = self.option_name(opt, optdict) | 
| currentvalue = getattr(self.config, optname, None) | 
| if currentvalue: | 
| currentvalue.update(value) | 
| value = currentvalue | 
| if action == 'store': | 
| -            setattr(self.config, self.option_attrname(opt, optdict), value) | 
| +            setattr(self.config, self.option_name(opt, optdict), value) | 
| elif action in ('store_true', 'count'): | 
| -            setattr(self.config, self.option_attrname(opt, optdict), 0) | 
| +            setattr(self.config, self.option_name(opt, optdict), 0) | 
| elif action == 'store_false': | 
| -            setattr(self.config, self.option_attrname(opt, optdict), 1) | 
| +            setattr(self.config, self.option_name(opt, optdict), 1) | 
| elif action == 'append': | 
| -            opt = self.option_attrname(opt, optdict) | 
| +            opt = self.option_name(opt, optdict) | 
| _list = getattr(self.config, opt, None) | 
| if _list is None: | 
| if isinstance(value, (list, tuple)): | 
| @@ -865,12 +839,12 @@ class OptionsProviderMixIn(object): | 
| defaultstr = ': ' | 
| else: | 
| defaultstr = '(default: %s): ' % format_option_value(optdict, default) | 
| -        print(':%s:' % option) | 
| -        print(optdict.get('help') or option) | 
| +        print ':%s:' % option | 
| +        print optdict.get('help') or option | 
| inputfunc = INPUT_FUNCTIONS[optdict['type']] | 
| value = inputfunc(optdict, defaultstr) | 
| while default is REQUIRED and not value: | 
| -            print('please specify a value') | 
| +            print 'please specify a value' | 
| value = inputfunc(optdict, '%s: ' % option) | 
| if value is None and default is not None: | 
| value = default | 
| @@ -919,7 +893,6 @@ class OptionsProviderMixIn(object): | 
| for optname, optdict in options: | 
| yield (optname, optdict, self.option_value(optname)) | 
|  | 
| -# configuration ################################################################ | 
|  | 
| class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): | 
| """basic mixin for simple configurations which don't need the | 
| @@ -940,7 +913,7 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): | 
| continue | 
| if not gdef in self.option_groups: | 
| self.option_groups.append(gdef) | 
| -        self.register_options_provider(self, own_group=False) | 
| +        self.register_options_provider(self, own_group=0) | 
|  | 
| def register_options(self, options): | 
| """add some options to the configuration""" | 
| @@ -959,8 +932,8 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): | 
|  | 
| def __getitem__(self, key): | 
| try: | 
| -            return getattr(self.config, self.option_attrname(key)) | 
| -        except (optik_ext.OptionValueError, AttributeError): | 
| +            return getattr(self.config, self.option_name(key)) | 
| +        except (optparse.OptionValueError, AttributeError): | 
| raise KeyError(key) | 
|  | 
| def __setitem__(self, key, value): | 
| @@ -968,7 +941,7 @@ class ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn): | 
|  | 
| def get(self, key, default=None): | 
| try: | 
| -            return getattr(self.config, self.option_attrname(key)) | 
| +            return getattr(self.config, self.option_name(key)) | 
| except (OptionError, AttributeError): | 
| return default | 
|  | 
| @@ -1004,21 +977,20 @@ class OptionsManager2ConfigurationAdapter(object): | 
| def __getitem__(self, key): | 
| provider = self.config._all_options[key] | 
| try: | 
| -            return getattr(provider.config, provider.option_attrname(key)) | 
| +            return getattr(provider.config, provider.option_name(key)) | 
| except AttributeError: | 
| raise KeyError(key) | 
|  | 
| def __setitem__(self, key, value): | 
| -        self.config.global_set_option(self.config.option_attrname(key), value) | 
| +        self.config.global_set_option(self.config.option_name(key), value) | 
|  | 
| def get(self, key, default=None): | 
| provider = self.config._all_options[key] | 
| try: | 
| -            return getattr(provider.config, provider.option_attrname(key)) | 
| +            return getattr(provider.config, provider.option_name(key)) | 
| except AttributeError: | 
| return default | 
|  | 
| -# other functions ############################################################## | 
|  | 
| def read_old_config(newconfig, changes, configfile): | 
| """initialize newconfig from a deprecated configuration file | 
| @@ -1083,13 +1055,8 @@ def read_old_config(newconfig, changes, configfile): | 
| newconfig.set_option(optname, oldconfig[optname], optdict=optdef) | 
|  | 
|  | 
| -def merge_options(options, optgroup=None): | 
| -    """preprocess a list of options and remove duplicates, returning a new list | 
| -    (tuple actually) of options. | 
| - | 
| -    Options dictionaries are copied to avoid later side-effect. Also, if | 
| -    `otpgroup` argument is specified, ensure all options are in the given group. | 
| -    """ | 
| +def merge_options(options): | 
| +    """preprocess options to remove duplicate""" | 
| alloptions = {} | 
| options = list(options) | 
| for i in range(len(options)-1, -1, -1): | 
| @@ -1098,9 +1065,5 @@ def merge_options(options, optgroup=None): | 
| options.pop(i) | 
| alloptions[optname].update(optdict) | 
| else: | 
| -            optdict = optdict.copy() | 
| -            options[i] = (optname, optdict) | 
| alloptions[optname] = optdict | 
| -        if optgroup is not None: | 
| -            alloptions[optname]['group'] = optgroup | 
| return tuple(options) | 
|  |