import ConfigParser class OrderedRawConfigParser( ConfigParser.RawConfigParser ): """ Overload standard Class ConfigParser.RawConfigParser """ def write(self, fp): """Write an .ini-format representation of the configuration state.""" if self._defaults: fp.write("[%s]\n" % DEFAULTSECT) for key in sorted( self._defaults ): fp.write( "%s = %s\n" % (key, str( self._defaults[ key ] ).replace('\n', '\n\t')) ) fp.write("\n") for section in self._sections: fp.write("[%s]\n" % section) for key in sorted( self._sections[section] ): if key != "__name__": fp.write("%s = %s\n" % (key, str( self._sections[section][ key ] ).replace('\n', '\n\t'))) fp.write("\n") optionxform = str _NOTFOUND = object() class Flipdict(dict): """An injective (one-to-one) python dict. Ensures that each key maps to a unique value, and each value maps back to that same key. Code mostly taken from here: http://code.activestate.com/recipes/576968-flipdict-python-dict-that-also-maintains-a-one-to-/ """ def __init__(self, *args, **kw): self._flip = dict.__new__(self.__class__) setattr(self._flip, "_flip", self) for key, val in dict(*args, **kw).iteritems(): self[key] = val @property def flip(self): """The inverse mapping.""" return self._flip def __repr__(self): return "%s(%r)" % (self.__class__.__name__, dict(self)) __str__ = __repr__ def copy(self): return self.__class__(self) @classmethod def fromkeys(cls, keys, value=None): return cls(dict.fromkeys(keys, value)) def __setitem__(self, key, val): k = self._flip.get(val, _NOTFOUND) if not (k is _NOTFOUND or k==key): raise KeyError('(key,val) would erase mapping for value %r' % val) v = self.get(key, _NOTFOUND) if v is not _NOTFOUND: dict.__delitem__(self._flip, v) dict.__setitem__(self, key, val) dict.__setitem__(self._flip, val, key) def setdefault(self, key, default = None): # Copied from python's UserDict.DictMixin code. try: return self[key] except KeyError: self[key] = default return default def update(self, other = None, **kwargs): # Copied from python's UserDict.DictMixin code. # Make progressively weaker assumptions about "other" if other is None: pass elif hasattr(other, 'iteritems'): # iteritems saves memory and lookups for k, v in other.iteritems(): self[k] = v elif hasattr(other, 'keys'): for k in other.keys(): self[k] = other[k] else: for k, v in other: self[k] = v if kwargs: self.update(kwargs) def __delitem__(self, key): val = dict.pop(self, key) dict.__delitem__(self._flip, val) def pop(self, key, *args): val = dict.pop(self, key, *args) dict.__delitem__(self._flip, val) return val def popitem(self): key, val = dict.popitem(self) dict.__delitem__(self._flip, val) return key, val def clear(self): dict.clear(self) dict.clear(self._flip)