Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: chainedconfigparser.py

Issue 9190147: Allow metadata file to inherit values from another configuration file (Closed)
Patch Set: Make option source directory available Created Nov. 5, 2013, 12:44 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chainedconfigparser.py
===================================================================
--- a/chainedconfigparser.py
+++ b/chainedconfigparser.py
@@ -15,16 +15,22 @@
# You should have received a copy of the GNU General Public License
# along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
# Note: These are the base functions common to all packagers, the actual
# packagers are implemented in packagerGecko and packagerChrome.
import os, codecs, ConfigParser
+class Item(tuple):
+ def __new__(cls, name, value, source):
+ result = super(Item, cls).__new__(cls, (name, value))
+ result.source = source
+ return result
+
class ChainedConfigParser:
"""
This class provides essentially the same interfaces as SafeConfigParser but
allows chaining configuration files so that one config file provides the
default values for the other. To specify the config file to inherit from
a config file needs to contain the following option:
[default]
@@ -32,29 +38,33 @@ class ChainedConfigParser:
The value of the inherit option has to be a relative path with forward
slashes as delimiters. Up to 5 configuration files can be chained this way,
longer chains are disallowed to deal with circular references.
A main API difference to SafeConfigParser is the way a class instance is
constructed: a file path has to be passed, this file is assumed to be
encoded as UTF-8. Also, ChainedConfigParser data is read-only and the
- options are case-sensitive.
+ options are case-sensitive. An additional option_source(section, option)
+ method is provided to get the path of the configuration file defining this
+ option (for relative paths). Items returned by the items() function also
+ have a source attribute serving the same purpose.
"""
def __init__(self, path):
self.chain = []
self.read_path(path)
def read_path(self, path):
if len(self.chain) >= 5:
raise Exception('Too much inheritance in config files')
config = ConfigParser.SafeConfigParser()
config.optionxform = str
+ config.source_path = path
handle = codecs.open(path, 'rb', encoding='utf-8')
config.readfp(handle)
handle.close()
self.chain.append(config)
if config.has_section('default') and config.has_option('default', 'inherit'):
parts = config.get('default', 'inherit').split('/')
defaults_path = os.path.join(os.path.dirname(path), *parts)
@@ -103,10 +113,16 @@ class ChainedConfigParser:
def items(self, section):
seen = set()
result = []
for config in self.chain:
if config.has_section(section):
for name, value in config.items(section):
if name not in seen:
seen.add(name)
- result.append((name, value))
+ result.append(Item(name, value, config.source_path))
return result
+
+ def option_source(self, section, option):
+ for config in self.chain:
+ if config.has_section(section) and config.has_option(section, option):
+ return config.source_path
+ raise ConfigParser.NoOptionError(option, section)
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld