Bug 1047267 - Add a memoize decorator to the mozbuild module. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 07 Aug 2014 14:20:37 +0900
changeset 198270 12d00374d8138e078eea5f3427c95f5e411d4419
parent 198269 a5abcc000a5713ce41627c93c0487781b9d258e1
child 198271 698ae2f2c8bf4d4205cb8d8683595b30a840db51
push id27265
push useremorley@mozilla.com
push dateThu, 07 Aug 2014 12:49:34 +0000
treeherdermozilla-central@bf5cbb36f4d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1047267
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1047267 - Add a memoize decorator to the mozbuild module. r=gps
python/mozbuild/mozbuild/test/test_util.py
python/mozbuild/mozbuild/util.py
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -15,16 +15,17 @@ from mozfile.mozfile import NamedTempora
 from mozunit import (
     main,
     MockedOpen,
 )
 
 from mozbuild.util import (
     FileAvoidWrite,
     hash_file,
+    memoize,
     resolve_target_to_make,
     MozbuildDeletionError,
     HierarchicalStringList,
     HierarchicalStringListWithFlagsFactory,
     StrictOrderingOnAppendList,
     StrictOrderingOnAppendListWithFlagsFactory,
     UnsortedError,
 )
@@ -424,10 +425,32 @@ class TestHierarchicalStringListWithFlag
 
         l.x['y'].foo = True
         self.assertEqual(l.x['y'].foo, True)
 
         with self.assertRaises(AttributeError):
             l.x['y'].baz = False
 
 
+class TestMemoize(unittest.TestCase):
+    def test_memoize(self):
+        self._count = 0
+        @memoize
+        def wrapped(a, b):
+            self._count += 1
+            return a + b
+
+        self.assertEqual(wrapped(1, 1), 2)
+        self.assertEqual(self._count, 1)
+        self.assertEqual(wrapped(1, 1), 2)
+        self.assertEqual(self._count, 1)
+        self.assertEqual(wrapped(2, 1), 3)
+        self.assertEqual(self._count, 2)
+        self.assertEqual(wrapped(1, 2), 3)
+        self.assertEqual(self._count, 3)
+        self.assertEqual(wrapped(1, 2), 3)
+        self.assertEqual(self._count, 3)
+        self.assertEqual(wrapped(1, 1), 2)
+        self.assertEqual(self._count, 3)
+
+
 if __name__ == '__main__':
     main()
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -15,16 +15,17 @@ import os
 import stat
 import sys
 import time
 
 from collections import (
     defaultdict,
     OrderedDict,
 )
+from functools import wraps
 from StringIO import StringIO
 
 
 if sys.version_info[0] == 3:
     str_type = str
 else:
     str_type = basestring
 
@@ -701,8 +702,19 @@ class OrderedDefaultDict(OrderedDict):
         self._default_factory = default_factory
 
     def __getitem__(self, key):
         try:
             return OrderedDict.__getitem__(self, key)
         except KeyError:
             value = self[key] = self._default_factory()
             return value
+
+
+def memoize(func):
+    cache = {}
+
+    @wraps(func)
+    def wrapper(*args):
+        if args not in cache:
+            cache[args] = func(*args)
+        return cache[args]
+    return wrapper