diff --git a/oslo_i18n/_gettextutils.py b/oslo_i18n/_gettextutils.py index 9153b36..00028a6 100644 --- a/oslo_i18n/_gettextutils.py +++ b/oslo_i18n/_gettextutils.py @@ -99,3 +99,29 @@ def get_available_languages(domain): _AVAILABLE_LANGUAGES[domain] = result return copy.copy(result) + + +_original_find = gettext.find +_FIND_CACHE = {} + + +def cached_find(domain, localedir=None, languages=None, all=0): + """A version of gettext.find using a cache. + + gettext.find looks for mo files on the disk using os.path.exists. Those + don't tend to change over time, but the system calls pile up with a + long-running service. This caches the result so that we return the same mo + files, and only call find once per domain. + """ + key = (domain, + localedir, + tuple(languages) if languages is not None else None, + all) + if key in _FIND_CACHE: + return _FIND_CACHE[key] + result = _original_find(domain, localedir, languages, all) + _FIND_CACHE[key] = result + return result + + +gettext.find = cached_find diff --git a/oslo_i18n/tests/test_gettextutils.py b/oslo_i18n/tests/test_gettextutils.py index 6a30a95..2eca069 100644 --- a/oslo_i18n/tests/test_gettextutils.py +++ b/oslo_i18n/tests/test_gettextutils.py @@ -129,3 +129,13 @@ class GettextTest(test_base.BaseTestCase): unknown_domain_languages = _gettextutils.get_available_languages('huh') self.assertEqual(1, len(unknown_domain_languages)) self.assertIn('en_US', unknown_domain_languages) + + def test_cached_find(self): + domain = 'my-unique-domain' + key = (domain, None, None, 0) + self.assertNotIn(key, _gettextutils._FIND_CACHE) + gettext.find(domain) + self.assertIn(key, _gettextutils._FIND_CACHE) + _gettextutils._FIND_CACHE[key] = "spoof result" + self.assertEqual("spoof result", gettext.find(domain)) + _gettextutils._FIND_CACHE.pop(key)