Rev 6093: Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only. in file:///home/vila/src/bzr/experimental/expand-in-stack/

Vincent Ladeuil v.ladeuil+lp at free.fr
Fri Sep 2 14:30:23 UTC 2011


At file:///home/vila/src/bzr/experimental/expand-in-stack/

------------------------------------------------------------
revno: 6093
revision-id: v.ladeuil+lp at free.fr-20110902143023-61h8n8cm3r96lov9
parent: v.ladeuil+lp at free.fr-20110902062132-dq9y0slcwe28op73
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: expand-in-stack
timestamp: Fri 2011-09-02 16:30:23 +0200
message:
  Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
-------------- next part --------------
=== modified file 'bzrlib/config.py'
--- a/bzrlib/config.py	2011-09-02 06:21:32 +0000
+++ b/bzrlib/config.py	2011-09-02 14:30:23 +0000
@@ -2422,18 +2422,28 @@
 
 
 def list_from_store(unicode_str):
+    if not isinstance(unicode_str, basestring):
+        raise TypeError
+    # Use a an empty dict to initialize an empty configobj avoiding all
+    # parsing and encoding checks
+    c = ConfigObj({}, encoding='utf-8')
+    # Now inject our string directly as unicode All callers got their value
+    # from configobj, so values that need to be quoted are already properly
+    # quoted.
+    c._parse([u"list=%s" % (unicode_str,)])
+    co_list_or_not = c['list']
     # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
-    if isinstance(unicode_str, (str, unicode)):
-        if unicode_str:
+    if isinstance(co_list_or_not, basestring):
+        if co_list_or_not:
             # A single value, most probably the user forgot (or didn't care to
             # add) the final ','
-            l = [unicode_str]
+            l = [co_list_or_not]
         else:
             # The empty string, convert to empty list
             l = []
     else:
         # We rely on ConfigObj providing us with a list already
-        l = unicode_str
+        l = co_list_or_not
     return l
 
 
@@ -2705,7 +2715,8 @@
         co_input = StringIO(bytes)
         try:
             # The config files are always stored utf8-encoded
-            self._config_obj = ConfigObj(co_input, encoding='utf-8')
+            self._config_obj = ConfigObj(co_input, encoding='utf-8',
+                                         list_values=False)
         except configobj.ConfigObjError, e:
             self._config_obj = None
             raise errors.ParseConfigError(e.errors, self.external_url())

=== modified file 'bzrlib/tests/test_config.py'
--- a/bzrlib/tests/test_config.py	2011-09-02 06:21:32 +0000
+++ b/bzrlib/tests/test_config.py	2011-09-02 14:30:23 +0000
@@ -2443,8 +2443,11 @@
                              from_unicode=config.list_from_store)
 
     def test_convert_invalid(self):
+        opt = self.get_option()
+        # We don't even try to convert a list into a list, we only expect
+        # strings
+        self.assertConvertInvalid(opt, [1])
         # No string is invalid as all forms can be converted to a list
-        pass
 
     def test_convert_valid(self):
         opt = self.get_option()
@@ -2457,10 +2460,6 @@
         self.assertConverted([u'42'], opt, u'42')
         # A single string
         self.assertConverted([u'bar'], opt, u'bar')
-        # A list remains a list (configObj will turn a string containing commas
-        # into a list, but that's not what we're testing here)
-        self.assertConverted([u'foo', u'1', u'True'],
-                             opt, [u'foo', u'1', u'True'])
 
 
 class TestOptionRegistry(tests.TestCase):
@@ -2869,8 +2868,10 @@
         sections = list(store.get_sections())
         self.assertLength(4, sections)
         # The default section has no name.
-        # List values are provided as lists
-        self.assertSectionContent((None, {'foo': 'bar', 'l': ['1', '2']}),
+        # List values are provided as strings and need to be explicitly
+        # converted by specifying from_unicode=list_from_store at option
+        # registration
+        self.assertSectionContent((None, {'foo': 'bar', 'l': u'1,2'}),
                                   sections[0])
         self.assertSectionContent(
             ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
@@ -3329,6 +3330,16 @@
         self.conf.store._load_from_string('foo=m,o,r,e')
         self.assertEquals(['m', 'o', 'r', 'e'], self.conf.get('foo'))
 
+    def test_get_with_list_converter_embedded_spaces_many_items(self):
+        self.register_list_option('foo', None)
+        self.conf.store._load_from_string('foo=" bar", "baz "')
+        self.assertEquals([' bar', 'baz '], self.conf.get('foo'))
+
+    def test_get_with_list_converter_stripped_spaces_many_items(self):
+        self.register_list_option('foo', None)
+        self.conf.store._load_from_string('foo= bar ,  baz ')
+        self.assertEquals(['bar', 'baz'], self.conf.get('foo'))
+
 
 class TestStackExpandOptions(tests.TestCaseWithTransport):
 
@@ -3413,6 +3424,8 @@
 baz=end
 list={foo},{bar},{baz}
 ''')
+        self.registry.register(
+            config.Option('list', from_unicode=config.list_from_store))
         self.assertEquals(['start', 'middle', 'end'],
                            self.conf.get('list', expand=True))
 
@@ -3423,6 +3436,8 @@
 baz=end
 list={foo}
 ''')
+        self.registry.register(
+            config.Option('list', from_unicode=config.list_from_store))
         self.assertEquals(['start', 'middle', 'end'],
                            self.conf.get('list', expand=True))
 
@@ -3435,9 +3450,11 @@
 end=bar}
 hidden={start}{middle}{end}
 ''')
-        # Nope, it's either a string or a list, and the list wins as soon as a
-        # ',' appears, so the string concatenation never occur.
-        self.assertEquals(['{foo', '}', '{', 'bar}'],
+        # What matters is what the registration says, the conversion happends
+        # only after all expansions have been performed
+        self.registry.register(
+            config.Option('hidden', from_unicode=config.list_from_store))
+        self.assertEquals(['bin', 'go'],
                           self.conf.get('hidden', expand=True))
 
 



More information about the bazaar-commits mailing list