We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Overlaid Config Files are applied in reverse order
http://www.pantsbuild.org/options.html#overlaying-config-files documents that one can do:

    $ ./pants --pants-config-files=a.ini --pants-config-files=b.ini options --options-name="level"
    level = info (from CONFIG in a.ini)

    $ cat a.ini
    [GLOBAL]
    level: info

    $ cat b.ini
    [GLOBAL]
    level: debug

According to the docs, the second --pants-config-files should overlay the earlier values, but this is not happening :/

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/python/pants/option/config.py`
Content:
```
1 # coding=utf-8
2 # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
3 # Licensed under the Apache License, Version 2.0 (see LICENSE).
4 
5 from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
6                         unicode_literals, with_statement)
7 
8 import getpass
9 import itertools
10 import os
11 
12 import six
13 from six.moves import configparser
14 from twitter.common.collections import OrderedSet
15 
16 from pants.base.build_environment import get_buildroot, get_pants_cachedir, get_pants_configdir
17 from pants.util.eval import parse_expression
18 from pants.util.meta import AbstractClass
19 
20 
21 class Config(AbstractClass):
22   """Encapsulates ini-style config file loading and access.
23 
24   Supports recursive variable substitution using standard python format strings. E.g.,
25   %(var_name)s will be replaced with the value of var_name.
26   """
27   DEFAULT_SECTION = configparser.DEFAULTSECT
28 
29   class ConfigError(Exception):
30     pass
31 
32   class ConfigValidationError(ConfigError):
33     pass
34 
35   @classmethod
36   def load(cls, configpaths, seed_values=None):
37     """Loads config from the given paths.
38 
39     A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT
40     section, and be available for use in substitutions.  The caller may override some of these
41     seed values.
42 
43     :param list configpaths: Load from these paths. Later instances take precedence over earlier
44                              ones. If empty, returns an empty config.
45     :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,
46                         pants_supportdir and pants_distdir.
47     """
48     if not configpaths:
49       return _EmptyConfig()
50 
51     single_file_configs = []
52     for configpath in configpaths:
53       parser = cls._create_parser(seed_values)
54       with open(configpath, 'r') as ini:
55         parser.readfp(ini)
56       single_file_configs.append(_SingleFileConfig(configpath, parser))
57     return _ChainedConfig(single_file_configs)
58 
59   @classmethod
60   def _create_parser(cls, seed_values=None):
61     """Creates a config parser that supports %([key-name])s value substitution.
62 
63     A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT
64     section, and be available for use in substitutions.  The caller may override some of these
65     seed values.
66 
67     :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,
68                         pants_supportdir and pants_distdir.
69     """
70     seed_values = seed_values or {}
71     buildroot = seed_values.get('buildroot', get_buildroot())
72 
73     all_seed_values = {
74       'buildroot': buildroot,
75       'homedir': os.path.expanduser('~'),
76       'user': getpass.getuser(),
77       'pants_bootstrapdir': get_pants_cachedir(),
78       'pants_configdir': get_pants_configdir(),
79     }
80 
81     def update_dir_from_seed_values(key, default):
82       all_seed_values[key] = seed_values.get(key, os.path.join(buildroot, default))
83     update_dir_from_seed_values('pants_workdir', '.pants.d')
84     update_dir_from_seed_values('pants_supportdir', 'build-support')
85     update_dir_from_seed_values('pants_distdir', 'dist')
86 
87     return configparser.SafeConfigParser(all_seed_values)
88 
89   def get(self, section, option, type_=six.string_types, default=None):
90     """Retrieves option from the specified section (or 'DEFAULT') and attempts to parse it as type.
91 
92     If the specified section does not exist or is missing a definition for the option, the value is
93     looked up in the DEFAULT section.  If there is still no definition found, the default value
94     supplied is returned.
95     """
96     return self._getinstance(section, option, type_, default)
97 
98   def _getinstance(self, section, option, type_, default=None):
99     if not self.has_option(section, option):
100       return default
101 
102     raw_value = self.get_value(section, option)
103     # We jump through some hoops here to deal with the fact that `six.string_types` is a tuple of
104     # types.
105     if (type_ == six.string_types or
106         (isinstance(type_, type) and issubclass(type_, six.string_types))):
107       return raw_value
108 
109     key = '{}.{}'.format(section, option)
110     return parse_expression(name=key, val=raw_value, acceptable_types=type_,
111                             raise_type=self.ConfigError)
112 
113   # Subclasses must implement.
114   def configs(self):
115     """Returns the underlying single-file configs represented by this object."""
116     raise NotImplementedError()
117 
118   def sources(self):
119     """Returns the sources of this config as a list of filenames."""
120     raise NotImplementedError()
121 
122   def sections(self):
123     """Returns the sections in this config (not including DEFAULT)."""
124     raise NotImplementedError()
125 
126   def has_section(self, section):
127     """Returns whether this config has the section."""
128     raise NotImplementedError()
129 
130   def has_option(self, section, option):
131     """Returns whether this config specified a value the option."""
132     raise NotImplementedError()
133 
134   def get_value(self, section, option):
135     """Returns the value of the option in this config as a string, or None if no value specified."""
136     raise NotImplementedError()
137 
138   def get_source_for_option(self, section, option):
139     """Returns the path to the source file the given option was defined in.
140 
141     :param string section: the scope of the option.
142     :param string option: the name of the option.
143     :returns: the path to the config file, or None if the option was not defined by a config file.
144     :rtype: string
145     """
146     raise NotImplementedError
147 
148 
149 class _EmptyConfig(Config):
150   """A dummy config with no data at all."""
151 
152   def sources(self):
153     return []
154 
155   def configs(self):
156     return []
157 
158   def sections(self):
159     return []
160 
161   def has_section(self, section):
162     return False
163 
164   def has_option(self, section, option):
165     return False
166 
167   def get_value(self, section, option):
168     return None
169 
170   def get_source_for_option(self, section, option):
171     return None
172 
173 
174 class _SingleFileConfig(Config):
175   """Config read from a single file."""
176 
177   def __init__(self, configpath, configparser):
178     super(_SingleFileConfig, self).__init__()
179     self.configpath = configpath
180     self.configparser = configparser
181 
182   def configs(self):
183     return [self]
184 
185   def sources(self):
186     return [self.configpath]
187 
188   def sections(self):
189     return self.configparser.sections()
190 
191   def has_section(self, section):
192     return self.configparser.has_section(section)
193 
194   def has_option(self, section, option):
195     return self.configparser.has_option(section, option)
196 
197   def get_value(self, section, option):
198     return self.configparser.get(section, option)
199 
200   def get_source_for_option(self, section, option):
201     if self.has_option(section, option):
202       return self.sources()[0]
203     return None
204 
205 
206 class _ChainedConfig(Config):
207   """Config read from multiple sources."""
208 
209   def __init__(self, configs):
210     """
211     :param configs: A list of Config instances to chain.
212                     Later instances take precedence over earlier ones.
213     """
214     super(_ChainedConfig, self).__init__()
215     self._configs = list(reversed(configs))
216 
217   def configs(self):
218     return self._configs
219 
220   def sources(self):
221     return list(itertools.chain.from_iterable(cfg.sources() for cfg in self._configs))
222 
223   def sections(self):
224     ret = OrderedSet()
225     for cfg in self._configs:
226       ret.update(cfg.sections())
227     return ret
228 
229   def has_section(self, section):
230     for cfg in self._configs:
231       if cfg.has_section(section):
232         return True
233     return False
234 
235   def has_option(self, section, option):
236     for cfg in self._configs:
237       if cfg.has_option(section, option):
238         return True
239     return False
240 
241   def get_value(self, section, option):
242     for cfg in self._configs:
243       try:
244         return cfg.get_value(section, option)
245       except (configparser.NoSectionError, configparser.NoOptionError):
246         pass
247     if not self.has_section(section):
248       raise configparser.NoSectionError(section)
249     raise configparser.NoOptionError(option, section)
250 
251   def get_source_for_option(self, section, option):
252     for cfg in self._configs:
253       if cfg.has_option(section, option):
254         return cfg.get_source_for_option(section, option)
255     return None
256
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/python/pants/option/config.py b/src/python/pants/option/config.py
--- a/src/python/pants/option/config.py
+++ b/src/python/pants/option/config.py
@@ -218,7 +218,8 @@
     return self._configs
 
   def sources(self):
-    return list(itertools.chain.from_iterable(cfg.sources() for cfg in self._configs))
+    # NB: Present the sources in the order we were given them.
+    return list(itertools.chain.from_iterable(cfg.sources() for cfg in reversed(self._configs)))
 
   def sections(self):
     ret = OrderedSet()

{"golden_diff": "diff --git a/src/python/pants/option/config.py b/src/python/pants/option/config.py\n--- a/src/python/pants/option/config.py\n+++ b/src/python/pants/option/config.py\n@@ -218,7 +218,8 @@\n     return self._configs\n \n   def sources(self):\n-    return list(itertools.chain.from_iterable(cfg.sources() for cfg in self._configs))\n+    # NB: Present the sources in the order we were given them.\n+    return list(itertools.chain.from_iterable(cfg.sources() for cfg in reversed(self._configs)))\n \n   def sections(self):\n     ret = OrderedSet()\n", "issue": "Overlaid Config Files are applied in reverse order\nhttp://www.pantsbuild.org/options.html#overlaying-config-files documents that one can do:\r\n\r\n    $ ./pants --pants-config-files=a.ini --pants-config-files=b.ini options --options-name=\"level\"\r\n    level = info (from CONFIG in a.ini)\r\n\r\n    $ cat a.ini\r\n    [GLOBAL]\r\n    level: info\r\n\r\n    $ cat b.ini\r\n    [GLOBAL]\r\n    level: debug\r\n\r\nAccording to the docs, the second --pants-config-files should overlay the earlier values, but this is not happening :/\n", "before_files": [{"content": "# coding=utf-8\n# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import (absolute_import, division, generators, nested_scopes, print_function,\n                        unicode_literals, with_statement)\n\nimport getpass\nimport itertools\nimport os\n\nimport six\nfrom six.moves import configparser\nfrom twitter.common.collections import OrderedSet\n\nfrom pants.base.build_environment import get_buildroot, get_pants_cachedir, get_pants_configdir\nfrom pants.util.eval import parse_expression\nfrom pants.util.meta import AbstractClass\n\n\nclass Config(AbstractClass):\n  \"\"\"Encapsulates ini-style config file loading and access.\n\n  Supports recursive variable substitution using standard python format strings. E.g.,\n  %(var_name)s will be replaced with the value of var_name.\n  \"\"\"\n  DEFAULT_SECTION = configparser.DEFAULTSECT\n\n  class ConfigError(Exception):\n    pass\n\n  class ConfigValidationError(ConfigError):\n    pass\n\n  @classmethod\n  def load(cls, configpaths, seed_values=None):\n    \"\"\"Loads config from the given paths.\n\n    A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT\n    section, and be available for use in substitutions.  The caller may override some of these\n    seed values.\n\n    :param list configpaths: Load from these paths. Later instances take precedence over earlier\n                             ones. If empty, returns an empty config.\n    :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,\n                        pants_supportdir and pants_distdir.\n    \"\"\"\n    if not configpaths:\n      return _EmptyConfig()\n\n    single_file_configs = []\n    for configpath in configpaths:\n      parser = cls._create_parser(seed_values)\n      with open(configpath, 'r') as ini:\n        parser.readfp(ini)\n      single_file_configs.append(_SingleFileConfig(configpath, parser))\n    return _ChainedConfig(single_file_configs)\n\n  @classmethod\n  def _create_parser(cls, seed_values=None):\n    \"\"\"Creates a config parser that supports %([key-name])s value substitution.\n\n    A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT\n    section, and be available for use in substitutions.  The caller may override some of these\n    seed values.\n\n    :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,\n                        pants_supportdir and pants_distdir.\n    \"\"\"\n    seed_values = seed_values or {}\n    buildroot = seed_values.get('buildroot', get_buildroot())\n\n    all_seed_values = {\n      'buildroot': buildroot,\n      'homedir': os.path.expanduser('~'),\n      'user': getpass.getuser(),\n      'pants_bootstrapdir': get_pants_cachedir(),\n      'pants_configdir': get_pants_configdir(),\n    }\n\n    def update_dir_from_seed_values(key, default):\n      all_seed_values[key] = seed_values.get(key, os.path.join(buildroot, default))\n    update_dir_from_seed_values('pants_workdir', '.pants.d')\n    update_dir_from_seed_values('pants_supportdir', 'build-support')\n    update_dir_from_seed_values('pants_distdir', 'dist')\n\n    return configparser.SafeConfigParser(all_seed_values)\n\n  def get(self, section, option, type_=six.string_types, default=None):\n    \"\"\"Retrieves option from the specified section (or 'DEFAULT') and attempts to parse it as type.\n\n    If the specified section does not exist or is missing a definition for the option, the value is\n    looked up in the DEFAULT section.  If there is still no definition found, the default value\n    supplied is returned.\n    \"\"\"\n    return self._getinstance(section, option, type_, default)\n\n  def _getinstance(self, section, option, type_, default=None):\n    if not self.has_option(section, option):\n      return default\n\n    raw_value = self.get_value(section, option)\n    # We jump through some hoops here to deal with the fact that `six.string_types` is a tuple of\n    # types.\n    if (type_ == six.string_types or\n        (isinstance(type_, type) and issubclass(type_, six.string_types))):\n      return raw_value\n\n    key = '{}.{}'.format(section, option)\n    return parse_expression(name=key, val=raw_value, acceptable_types=type_,\n                            raise_type=self.ConfigError)\n\n  # Subclasses must implement.\n  def configs(self):\n    \"\"\"Returns the underlying single-file configs represented by this object.\"\"\"\n    raise NotImplementedError()\n\n  def sources(self):\n    \"\"\"Returns the sources of this config as a list of filenames.\"\"\"\n    raise NotImplementedError()\n\n  def sections(self):\n    \"\"\"Returns the sections in this config (not including DEFAULT).\"\"\"\n    raise NotImplementedError()\n\n  def has_section(self, section):\n    \"\"\"Returns whether this config has the section.\"\"\"\n    raise NotImplementedError()\n\n  def has_option(self, section, option):\n    \"\"\"Returns whether this config specified a value the option.\"\"\"\n    raise NotImplementedError()\n\n  def get_value(self, section, option):\n    \"\"\"Returns the value of the option in this config as a string, or None if no value specified.\"\"\"\n    raise NotImplementedError()\n\n  def get_source_for_option(self, section, option):\n    \"\"\"Returns the path to the source file the given option was defined in.\n\n    :param string section: the scope of the option.\n    :param string option: the name of the option.\n    :returns: the path to the config file, or None if the option was not defined by a config file.\n    :rtype: string\n    \"\"\"\n    raise NotImplementedError\n\n\nclass _EmptyConfig(Config):\n  \"\"\"A dummy config with no data at all.\"\"\"\n\n  def sources(self):\n    return []\n\n  def configs(self):\n    return []\n\n  def sections(self):\n    return []\n\n  def has_section(self, section):\n    return False\n\n  def has_option(self, section, option):\n    return False\n\n  def get_value(self, section, option):\n    return None\n\n  def get_source_for_option(self, section, option):\n    return None\n\n\nclass _SingleFileConfig(Config):\n  \"\"\"Config read from a single file.\"\"\"\n\n  def __init__(self, configpath, configparser):\n    super(_SingleFileConfig, self).__init__()\n    self.configpath = configpath\n    self.configparser = configparser\n\n  def configs(self):\n    return [self]\n\n  def sources(self):\n    return [self.configpath]\n\n  def sections(self):\n    return self.configparser.sections()\n\n  def has_section(self, section):\n    return self.configparser.has_section(section)\n\n  def has_option(self, section, option):\n    return self.configparser.has_option(section, option)\n\n  def get_value(self, section, option):\n    return self.configparser.get(section, option)\n\n  def get_source_for_option(self, section, option):\n    if self.has_option(section, option):\n      return self.sources()[0]\n    return None\n\n\nclass _ChainedConfig(Config):\n  \"\"\"Config read from multiple sources.\"\"\"\n\n  def __init__(self, configs):\n    \"\"\"\n    :param configs: A list of Config instances to chain.\n                    Later instances take precedence over earlier ones.\n    \"\"\"\n    super(_ChainedConfig, self).__init__()\n    self._configs = list(reversed(configs))\n\n  def configs(self):\n    return self._configs\n\n  def sources(self):\n    return list(itertools.chain.from_iterable(cfg.sources() for cfg in self._configs))\n\n  def sections(self):\n    ret = OrderedSet()\n    for cfg in self._configs:\n      ret.update(cfg.sections())\n    return ret\n\n  def has_section(self, section):\n    for cfg in self._configs:\n      if cfg.has_section(section):\n        return True\n    return False\n\n  def has_option(self, section, option):\n    for cfg in self._configs:\n      if cfg.has_option(section, option):\n        return True\n    return False\n\n  def get_value(self, section, option):\n    for cfg in self._configs:\n      try:\n        return cfg.get_value(section, option)\n      except (configparser.NoSectionError, configparser.NoOptionError):\n        pass\n    if not self.has_section(section):\n      raise configparser.NoSectionError(section)\n    raise configparser.NoOptionError(option, section)\n\n  def get_source_for_option(self, section, option):\n    for cfg in self._configs:\n      if cfg.has_option(section, option):\n        return cfg.get_source_for_option(section, option)\n    return None\n", "path": "src/python/pants/option/config.py"}], "after_files": [{"content": "# coding=utf-8\n# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import (absolute_import, division, generators, nested_scopes, print_function,\n                        unicode_literals, with_statement)\n\nimport getpass\nimport itertools\nimport os\n\nimport six\nfrom six.moves import configparser\nfrom twitter.common.collections import OrderedSet\n\nfrom pants.base.build_environment import get_buildroot, get_pants_cachedir, get_pants_configdir\nfrom pants.util.eval import parse_expression\nfrom pants.util.meta import AbstractClass\n\n\nclass Config(AbstractClass):\n  \"\"\"Encapsulates ini-style config file loading and access.\n\n  Supports recursive variable substitution using standard python format strings. E.g.,\n  %(var_name)s will be replaced with the value of var_name.\n  \"\"\"\n  DEFAULT_SECTION = configparser.DEFAULTSECT\n\n  class ConfigError(Exception):\n    pass\n\n  class ConfigValidationError(ConfigError):\n    pass\n\n  @classmethod\n  def load(cls, configpaths, seed_values=None):\n    \"\"\"Loads config from the given paths.\n\n    A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT\n    section, and be available for use in substitutions.  The caller may override some of these\n    seed values.\n\n    :param list configpaths: Load from these paths. Later instances take precedence over earlier\n                             ones. If empty, returns an empty config.\n    :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,\n                        pants_supportdir and pants_distdir.\n    \"\"\"\n    if not configpaths:\n      return _EmptyConfig()\n\n    single_file_configs = []\n    for configpath in configpaths:\n      parser = cls._create_parser(seed_values)\n      with open(configpath, 'r') as ini:\n        parser.readfp(ini)\n      single_file_configs.append(_SingleFileConfig(configpath, parser))\n    return _ChainedConfig(single_file_configs)\n\n  @classmethod\n  def _create_parser(cls, seed_values=None):\n    \"\"\"Creates a config parser that supports %([key-name])s value substitution.\n\n    A handful of seed values will be set to act as if specified in the loaded config file's DEFAULT\n    section, and be available for use in substitutions.  The caller may override some of these\n    seed values.\n\n    :param seed_values: A dict with optional override seed values for buildroot, pants_workdir,\n                        pants_supportdir and pants_distdir.\n    \"\"\"\n    seed_values = seed_values or {}\n    buildroot = seed_values.get('buildroot', get_buildroot())\n\n    all_seed_values = {\n      'buildroot': buildroot,\n      'homedir': os.path.expanduser('~'),\n      'user': getpass.getuser(),\n      'pants_bootstrapdir': get_pants_cachedir(),\n      'pants_configdir': get_pants_configdir(),\n    }\n\n    def update_dir_from_seed_values(key, default):\n      all_seed_values[key] = seed_values.get(key, os.path.join(buildroot, default))\n    update_dir_from_seed_values('pants_workdir', '.pants.d')\n    update_dir_from_seed_values('pants_supportdir', 'build-support')\n    update_dir_from_seed_values('pants_distdir', 'dist')\n\n    return configparser.SafeConfigParser(all_seed_values)\n\n  def get(self, section, option, type_=six.string_types, default=None):\n    \"\"\"Retrieves option from the specified section (or 'DEFAULT') and attempts to parse it as type.\n\n    If the specified section does not exist or is missing a definition for the option, the value is\n    looked up in the DEFAULT section.  If there is still no definition found, the default value\n    supplied is returned.\n    \"\"\"\n    return self._getinstance(section, option, type_, default)\n\n  def _getinstance(self, section, option, type_, default=None):\n    if not self.has_option(section, option):\n      return default\n\n    raw_value = self.get_value(section, option)\n    # We jump through some hoops here to deal with the fact that `six.string_types` is a tuple of\n    # types.\n    if (type_ == six.string_types or\n        (isinstance(type_, type) and issubclass(type_, six.string_types))):\n      return raw_value\n\n    key = '{}.{}'.format(section, option)\n    return parse_expression(name=key, val=raw_value, acceptable_types=type_,\n                            raise_type=self.ConfigError)\n\n  # Subclasses must implement.\n  def configs(self):\n    \"\"\"Returns the underlying single-file configs represented by this object.\"\"\"\n    raise NotImplementedError()\n\n  def sources(self):\n    \"\"\"Returns the sources of this config as a list of filenames.\"\"\"\n    raise NotImplementedError()\n\n  def sections(self):\n    \"\"\"Returns the sections in this config (not including DEFAULT).\"\"\"\n    raise NotImplementedError()\n\n  def has_section(self, section):\n    \"\"\"Returns whether this config has the section.\"\"\"\n    raise NotImplementedError()\n\n  def has_option(self, section, option):\n    \"\"\"Returns whether this config specified a value the option.\"\"\"\n    raise NotImplementedError()\n\n  def get_value(self, section, option):\n    \"\"\"Returns the value of the option in this config as a string, or None if no value specified.\"\"\"\n    raise NotImplementedError()\n\n  def get_source_for_option(self, section, option):\n    \"\"\"Returns the path to the source file the given option was defined in.\n\n    :param string section: the scope of the option.\n    :param string option: the name of the option.\n    :returns: the path to the config file, or None if the option was not defined by a config file.\n    :rtype: string\n    \"\"\"\n    raise NotImplementedError\n\n\nclass _EmptyConfig(Config):\n  \"\"\"A dummy config with no data at all.\"\"\"\n\n  def sources(self):\n    return []\n\n  def configs(self):\n    return []\n\n  def sections(self):\n    return []\n\n  def has_section(self, section):\n    return False\n\n  def has_option(self, section, option):\n    return False\n\n  def get_value(self, section, option):\n    return None\n\n  def get_source_for_option(self, section, option):\n    return None\n\n\nclass _SingleFileConfig(Config):\n  \"\"\"Config read from a single file.\"\"\"\n\n  def __init__(self, configpath, configparser):\n    super(_SingleFileConfig, self).__init__()\n    self.configpath = configpath\n    self.configparser = configparser\n\n  def configs(self):\n    return [self]\n\n  def sources(self):\n    return [self.configpath]\n\n  def sections(self):\n    return self.configparser.sections()\n\n  def has_section(self, section):\n    return self.configparser.has_section(section)\n\n  def has_option(self, section, option):\n    return self.configparser.has_option(section, option)\n\n  def get_value(self, section, option):\n    return self.configparser.get(section, option)\n\n  def get_source_for_option(self, section, option):\n    if self.has_option(section, option):\n      return self.sources()[0]\n    return None\n\n\nclass _ChainedConfig(Config):\n  \"\"\"Config read from multiple sources.\"\"\"\n\n  def __init__(self, configs):\n    \"\"\"\n    :param configs: A list of Config instances to chain.\n                    Later instances take precedence over earlier ones.\n    \"\"\"\n    super(_ChainedConfig, self).__init__()\n    self._configs = list(reversed(configs))\n\n  def configs(self):\n    return self._configs\n\n  def sources(self):\n    # NB: Present the sources in the order we were given them.\n    return list(itertools.chain.from_iterable(cfg.sources() for cfg in reversed(self._configs)))\n\n  def sections(self):\n    ret = OrderedSet()\n    for cfg in self._configs:\n      ret.update(cfg.sections())\n    return ret\n\n  def has_section(self, section):\n    for cfg in self._configs:\n      if cfg.has_section(section):\n        return True\n    return False\n\n  def has_option(self, section, option):\n    for cfg in self._configs:\n      if cfg.has_option(section, option):\n        return True\n    return False\n\n  def get_value(self, section, option):\n    for cfg in self._configs:\n      try:\n        return cfg.get_value(section, option)\n      except (configparser.NoSectionError, configparser.NoOptionError):\n        pass\n    if not self.has_section(section):\n      raise configparser.NoSectionError(section)\n    raise configparser.NoOptionError(option, section)\n\n  def get_source_for_option(self, section, option):\n    for cfg in self._configs:\n      if cfg.has_option(section, option):\n        return cfg.get_source_for_option(section, option)\n    return None\n", "path": "src/python/pants/option/config.py"}]}