2029
2029
self.orig[name] = self.get(name, None)
2030
2030
del self.options[name]
2032
class Store(object):
2033
"""Abstract interface to persistent storage for configuration options."""
2039
raise NotImplementedError(self.load)
2042
class ConfigObjStore(Store):
2044
def __init__(self, transport, file_name):
2045
"""A config Store using ConfigObj for storage.
2047
:param transport: The transport object where the config file is located.
2049
:param file_name: The config file basename in the transport directory.
2051
super(ConfigObjStore, self).__init__()
2052
self.transport = transport
2053
self.file_name = file_name
2054
# No transient content is known initially
2055
self._content = None
2058
def from_string(cls, str_or_unicode, transport, file_name, save=False):
2059
"""Create a config store from a string.
2061
:param str_or_unicode: A string representing the file content. This will
2062
be utf-8 encoded internally.
2064
:param transport: The transport object where the config file is located.
2066
:param file_name: The configuration file basename.
2068
:param _save: Whether the file should be saved upon creation.
2070
conf = cls(transport=transport, file_name=file_name)
2071
conf._create_from_string(str_or_unicode, save)
2074
def _create_from_string(self, str_or_unicode, save):
2075
# We just keep record the content waiting for load() to be called when
2077
self._content = StringIO(str_or_unicode.encode('utf-8'))
2078
# Some tests use in-memory configs, some other always need the config
2079
# file to exist on disk.
2084
"""Load the store from the associated file."""
2087
if self._content is not None:
2088
co_input = self._content
2090
# The config files are always stored utf8-encoded
2091
co_input = StringIO(self.transport.get_bytes(self.file_name))
2093
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2094
except configobj.ConfigObjError, e:
2095
# FIXME: external_url should really accepts an optional relpath
2096
# parameter (bug #750169) :-/ -- vila 2011-04-04
2097
# The following will do in the interim but maybe we don't want to
2098
# expose a path here but rather a config ID and its associated
2099
# object (hand wawing).
2100
file_path = os.path.join(self.transport.external_url(),
2102
raise errors.ParseConfigError(e.errors, file_path)
2033
2106
class cmd_config(commands.Command):
2034
2107
__doc__ = """Display, set or remove a configuration option.