Rev 5773: Replace class.from_string with self._load_from_string to all stores can use it. in file:///home/vila/src/bzr/experimental/config/

Vincent Ladeuil v.ladeuil+lp at free.fr
Tue Apr 12 07:06:59 UTC 2011


At file:///home/vila/src/bzr/experimental/config/

------------------------------------------------------------
revno: 5773
revision-id: v.ladeuil+lp at free.fr-20110412070658-mig3cbgqbf0yyt5j
parent: v.ladeuil+lp at free.fr-20110409201100-o3r9zl69tssv9mla
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: config-abstract-store
timestamp: Tue 2011-04-12 09:06:58 +0200
message:
  Replace  class.from_string with self._load_from_string to all stores can use it.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2011-04-09 20:11:00 +0000
+++ b/bzrlib/config.py	2011-04-12 07:06:58 +0000
@@ -2134,11 +2134,13 @@
             self.orig[name] = self.get(name, None)
         del self.options[name]
 
+
 class Store(object):
     """Abstract interface to persistent storage for configuration options."""
 
-    def __init__(self):
-        self.loaded = False
+    @property
+    def loaded(self):
+        raise NotImplementedError(self.loaded)
 
     def load(self):
         raise NotImplementedError(self.load)
@@ -2173,27 +2175,11 @@
         super(ConfigObjStore, self).__init__()
         self.transport = transport
         self.file_name = file_name
-        # No transient content is known initially
-        self._content = None
-
-    @classmethod
-    def from_string(cls, str_or_unicode, transport, file_name):
-        """Create a config store from a string.
-
-        :param str_or_unicode: A string representing the file content. This will
-            be utf-8 encoded internally.
-
-        :param transport: The transport object where the config file is located.
-
-        :param file_name: The configuration file basename.
-        """
-        conf = cls(transport=transport, file_name=file_name)
-        conf._create_from_string(str_or_unicode)
-        return conf
-
-    def _create_from_string(self, str_or_unicode):
-        # We just keep the content waiting for load() to be called when needed
-        self._content = StringIO(str_or_unicode.encode('utf-8'))
+        self._config_obj = None
+
+    @property
+    def loaded(self):
+        return self._config_obj != None
 
     def load(self, allow_no_such_file=False):
         """Load the store from the associated file.
@@ -2203,21 +2189,32 @@
         """
         if self.loaded:
             return
-        if self._content is not None:
-            co_input = self._content
-        else:
-            try:
-                content = self.transport.get_bytes(self.file_name)
-            except errors.NoSuchFile:
-                if allow_no_such_file:
-                    content = ''
-                else:
-                    raise
-            co_input =  StringIO(content)
+        try:
+            content = self.transport.get_bytes(self.file_name)
+        except errors.NoSuchFile:
+            if allow_no_such_file:
+                content = ''
+            else:
+                raise
+        self._load_from_string(content)
+
+    def _load_from_string(self, str_or_unicode):
+        """Create a config store from a string.
+
+        :param str_or_unicode: A string representing the file content. This will
+            be utf-8 encoded internally.
+
+        This is for tests and should not be used in production unless a
+        convincing use case can be demonstrated :)
+        """
+        if self.loaded:
+            raise AssertionError('Already loaded: %r' % (self._config_obj,))
+        co_input = StringIO(str_or_unicode.encode('utf-8'))
         try:
             # The config files are always stored utf8-encoded
             self._config_obj = ConfigObj(co_input, encoding='utf-8')
         except configobj.ConfigObjError, e:
+            self._config_obj = None
             # FIXME: external_url should really accepts an optional relpath
             # parameter (bug #750169) :-/ -- vila 2011-04-04
             # The following will do in the interim but maybe we don't want to
@@ -2226,14 +2223,11 @@
             file_path = os.path.join(self.transport.external_url(),
                                      self.file_name)
             raise errors.ParseConfigError(e.errors, file_path)
-        self.loaded = True
 
     def save(self):
         out = StringIO()
         self._config_obj.write(out)
         self.transport.put_bytes(self.file_name, out.getvalue())
-        # We don't need the transient content anymore
-        self._content = None
 
     def get_sections(self):
         """Get the configobj section in the file order.
@@ -2244,6 +2238,9 @@
         self.load()
         cobj = self._config_obj
         if cobj.scalars:
+
+# use self.readonly_section_kls
+
             yield ReadOnlySection(None, cobj)
         for section_name in cobj.sections:
             yield ReadOnlySection(section_name, cobj[section_name])
@@ -2255,6 +2252,9 @@
             section = self._config_obj
         else:
             section = self._config_obj.setdefault(section_name, {})
+
+# use self.mutable_section_kls
+
         return MutableSection(section_name, section)
 
 

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2011-04-09 20:11:00 +0000
+++ b/bzrlib/tests/test_config.py	2011-04-12 07:06:58 +0000
@@ -1898,12 +1898,13 @@
     If provided, the content is added to the store but without saving it on
     disk. It should be a string or a unicode string in the ConfigObj syntax.
     While this poses a constraint on other store implementations, it keeps a
-    simple syntax usable by test writers.
+    simple syntax usable by test writers. Note that the other store
+    implementations can rely on ConfigObj to parse the content and get the
+    option definitions and values from it.
     """
-    if content is None:
-        store = config.ConfigObjStore(transport, file_name)
-    else:
-        store = config.ConfigObjStore.from_string(content, transport, file_name)
+    store = config.ConfigObjStore(transport, file_name)
+    if content is not None:
+        store._load_from_string(content)
     return store
 
 
@@ -1933,13 +1934,6 @@
         store.load()
         self.assertEquals(True, store.loaded)
 
-    def test_from_string_delayed_load(self):
-        store = self.get_store('foo.conf', '')
-        self.assertEquals(False, store.loaded)
-        store.load()
-        # We loaded the store from the provided content
-        self.assertEquals(True, store.loaded)
-
     def test_get_no_sections_for_empty(self):
         store = self.get_store('foo.conf', '')
         store.load()
@@ -2022,10 +2016,11 @@
         self.assertRaises(errors.NoSuchFile, store.load)
 
     def test_invalid_content(self):
-        store = config.ConfigObjStore.from_string(
-            'this is invalid !', self.get_transport(), 'foo.conf', )
+        store = config.ConfigObjStore(self.get_transport(), 'foo.conf', )
         self.assertEquals(False, store.loaded)
-        exc = self.assertRaises(errors.ParseConfigError, store.load)
+        exc = self.assertRaises(
+            errors.ParseConfigError, store._load_from_string,
+            'this is invalid !')
         self.assertEndsWith(exc.filename, 'foo.conf')
         # And the load failed
         self.assertEquals(False, store.loaded)
@@ -2035,7 +2030,8 @@
         # option names share the same name space...)
         # FIXME: This should be fixed by forbidding dicts as values ?
         # -- vila 2011-04-05
-        store = config.ConfigObjStore.from_string('''
+        store = config.ConfigObjStore(self.get_transport(), 'foo.conf', )
+        store._load_from_string('''
 foo=bar
 l=1,2
 [DEFAULT]
@@ -2046,7 +2042,7 @@
 foo_in_baz=barbaz
 [[qux]]
 foo_in_qux=quux
-''', self.get_transport(), 'foo.conf')
+''')
         sections = list(store.get_sections())
         self.assertLength(4, sections)
         # The default section has no name.



More information about the bazaar-commits mailing list