Bug 1123980 - Part 1: Handle common prefixes in .properties lists and dicts. r=mshal a=sylvestre
authorNick Alexander <nalexander@mozilla.com>
Wed, 21 Jan 2015 14:31:22 -0800
changeset 243725 923404bb30ac
parent 243724 e1faea5d0942
child 243726 05befa69d765
push id4452
push usermfinkle@mozilla.com
push date2015-02-09 17:44 +0000
treeherdermozilla-beta@05befa69d765 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmshal, sylvestre
bugs1123980
milestone36.0
Bug 1123980 - Part 1: Handle common prefixes in .properties lists and dicts. r=mshal a=sylvestre This handles: list.0=A list.1=B list.sublist.0=C so that list=>[A, B] list.sublist=>[C] and dict=default dict.key1=A dict.key2=B so that dict=>{key1:A, key2:B} dict=>default
python/mozbuild/mozbuild/dotproperties.py
python/mozbuild/mozbuild/test/test_dotproperties.py
--- a/python/mozbuild/mozbuild/dotproperties.py
+++ b/python/mozbuild/mozbuild/dotproperties.py
@@ -52,29 +52,34 @@ class DotProperties:
         Returns [] to indicate an empty or missing list.'''
 
         if not prefix.endswith('.'):
             prefix = prefix + '.'
         indexes = []
         for k, v in self._properties.iteritems():
             if not k.startswith(prefix):
                 continue
-            indexes.append(int(k[len(prefix):]))
+            key = k[len(prefix):]
+            if '.' in key:
+                # We have something like list.sublist.0.
+                continue
+            indexes.append(int(key))
         return [self._properties[prefix + str(index)] for index in sorted(indexes)]
 
     def get_dict(self, prefix, required_keys=[]):
         '''Turns {'foo.title':'title', ...} into {'title':'title', ...}.
 
         If |required_keys| is present, it must be an iterable of required key
         names.  If a required key is not present, ValueError is thrown.
 
         Returns {} to indicate an empty or missing dict.'''
 
         if not prefix.endswith('.'):
             prefix = prefix + '.'
 
-        D = dict((k[len(prefix):], v) for k, v in self._properties.iteritems() if k.startswith(prefix))
+        D = dict((k[len(prefix):], v) for k, v in self._properties.iteritems()
+                 if k.startswith(prefix) and '.' not in k[len(prefix):])
 
         for required_key in required_keys:
             if not required_key in D:
                 raise ValueError('Required key %s not present' % required_key)
 
         return D
--- a/python/mozbuild/mozbuild/test/test_dotproperties.py
+++ b/python/mozbuild/mozbuild/test/test_dotproperties.py
@@ -60,31 +60,94 @@ order.0=A
 order.2=C
 ''')
         p = DotProperties(contents)
         self.assertEqual(p.get_list('missing'), [])
         self.assertEqual(p.get_list('list'), ['A', 'B', 'C'])
         self.assertEqual(p.get_list('order'), ['A', 'B', 'C'])
 
 
+    def test_get_list_with_shared_prefix(self):
+        contents = StringIO('''
+list.0=A
+list.1=B
+list.2=C
+
+list.sublist.1=E
+list.sublist.0=D
+list.sublist.2=F
+
+list.sublist.second.0=G
+
+list.other.0=H
+''')
+        p = DotProperties(contents)
+        self.assertEqual(p.get_list('list'), ['A', 'B', 'C'])
+        self.assertEqual(p.get_list('list.sublist'), ['D', 'E', 'F'])
+        self.assertEqual(p.get_list('list.sublist.second'), ['G'])
+        self.assertEqual(p.get_list('list.other'), ['H'])
+
+
     def test_get_dict(self):
         contents = StringIO('''
 A.title=title A
 
 B.title=title B
 B.url=url B
+
+C=value
 ''')
         p = DotProperties(contents)
         self.assertEqual(p.get_dict('missing'), {})
         self.assertEqual(p.get_dict('A'), {'title': 'title A'})
         self.assertEqual(p.get_dict('B'), {'title': 'title B', 'url': 'url B'})
         with self.assertRaises(ValueError):
             p.get_dict('A', required_keys=['title', 'url'])
         with self.assertRaises(ValueError):
             p.get_dict('missing', required_keys=['key'])
+        # A key=value pair is considered to root an empty dict.
+        self.assertEqual(p.get_dict('C'), {})
+        with self.assertRaises(ValueError):
+            p.get_dict('C', required_keys=['missing_key'])
+
+
+    def test_get_dict_with_shared_prefix(self):
+        contents = StringIO('''
+A.title=title A
+A.subdict.title=title A subdict
+
+B.title=title B
+B.url=url B
+B.subdict.title=title B subdict
+B.subdict.url=url B subdict
+''')
+        p = DotProperties(contents)
+        self.assertEqual(p.get_dict('A'), {'title': 'title A'})
+        self.assertEqual(p.get_dict('B'), {'title': 'title B', 'url': 'url B'})
+        self.assertEqual(p.get_dict('A.subdict'),
+            {'title': 'title A subdict'})
+        self.assertEqual(p.get_dict('B.subdict'),
+            {'title': 'title B subdict', 'url': 'url B subdict'})
+
+    def test_get_dict_with_value_prefix(self):
+        contents = StringIO('''
+A.default=A
+A.default.B=B
+A.default.B.ignored=B ignored
+A.default.C=C
+A.default.C.ignored=C ignored
+''')
+        p = DotProperties(contents)
+        self.assertEqual(p.get('A.default'), 'A')
+        # This enumerates the properties.
+        self.assertEqual(p.get_dict('A.default'), {'B': 'B', 'C': 'C'})
+        # They can still be fetched directly.
+        self.assertEqual(p.get('A.default.B'), 'B')
+        self.assertEqual(p.get('A.default.C'), 'C')
+
 
     def test_unicode(self):
         contents = StringIO('''
 # Danish.
 # ####  ~~ Søren Munk Skrøder, sskroeder - 2009-05-30 @ #mozmae
 
 # Korean.
 A.title=한메일