# config.py # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors # # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php """ Module containing module parser implementation able to properly read and write configuration files """ import re import os import ConfigParser as cp import inspect import cStringIO from git.odict import OrderedDict from git.utils import LockFile class _MetaParserBuilder(type): """ Utlity class wrapping base-class methods into decorators that assure read-only properties """ def __new__(metacls, name, bases, clsdict): """ Equip all base-class methods with a _needs_values decorator, and all non-const methods with a _set_dirty_and_flush_changes decorator in addition to that. """ mutating_methods = clsdict['_mutating_methods_'] for base in bases: methods = ( t for t in inspect.getmembers(base, inspect.ismethod) if not t[0].startswith("_") ) for name, method in methods: if name in clsdict: continue method_with_values = _needs_values(method) if name in mutating_methods: method_with_values = _set_dirty_and_flush_changes(method_with_values) # END mutating methods handling clsdict[name] = method_with_values # END for each base new_type = super(_MetaParserBuilder, metacls).__new__(metacls, name, bases, clsdict) return new_type def _needs_values(func): """ Returns method assuring we read values (on demand) before we try to access them """ def assure_data_present(self, *args, **kwargs): self.read() return func(self, *args, **kwargs) # END wrapper method assure_data_present.__name__ = func.__name__ return assure_data_present def _set_dirty_and_flush_changes(non_const_func): """ Return method that checks whether given non constant function may be called. If so, the instance will be set dirty. Additionally, we flush the changes right to disk """ def flush_changes(self, *args, **kwargs): rval = non_const_func(self, *args, **kwargs) self.write() return rval # END wrapper method flush_changes.__name__ = non_const_func.__name__ return flush_changes class GitConfigParser(cp.RawConfigParser, object): """ Implements specifics required to read git style configuration files. This variation behaves much like the git.config command such that the configuration will be read on demand based on the filepath given during initialization. The changes will automatically be written once the instance goes out of scope, but can be triggered manually as well. The configuration file will be locked if you intend to change values preventing other instances to write concurrently. NOTE The config is case-sensitive even when queried, hence section and option names must match perfectly. """ __metaclass__ = _MetaParserBuilder #{ Configuration # The lock type determines the type of lock to use in new configuration readers. # They must be compatible to the LockFile interface. # A suitable alternative would be the BlockingLockFile t_lock = LockFile #} END configuration OPTCRE = re.compile( r'\s?(?P