From bd2c44b71cf8d22235df4f187c814b3e0e490683 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Mon, 27 May 2019 10:50:41 +0300 Subject: Cache locale_identifiers() Fixes #620 --- babel/localedata.py | 17 ++++++++++++++--- tests/test_localedata.py | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/babel/localedata.py b/babel/localedata.py index 2a8c442..03381e2 100644 --- a/babel/localedata.py +++ b/babel/localedata.py @@ -57,13 +57,24 @@ def locale_identifiers(): """Return a list of all locale identifiers for which locale data is available. + This data is cached after the first invocation in `locale_identifiers.cache`. + + Removing the `locale_identifiers.cache` attribute or setting it to `None` + will cause this function to re-read the list from disk. + .. versionadded:: 0.8.1 :return: a list of locale identifiers (strings) """ - return [stem for stem, extension in [ - os.path.splitext(filename) for filename in os.listdir(_dirname) - ] if extension == '.dat' and stem != 'root'] + data = getattr(locale_identifiers, 'cache', None) + if data is None: + locale_identifiers.cache = data = [ + stem + for stem, extension in + (os.path.splitext(filename) for filename in os.listdir(_dirname)) + if extension == '.dat' and stem != 'root' + ] + return data def load(name, merge_inherited=True): diff --git a/tests/test_localedata.py b/tests/test_localedata.py index dceb984..bffe763 100644 --- a/tests/test_localedata.py +++ b/tests/test_localedata.py @@ -17,6 +17,7 @@ from operator import methodcaller from babel import localedata + class MergeResolveTestCase(unittest.TestCase): def test_merge_items(self): @@ -78,6 +79,7 @@ def test_locale_identification(): for l in localedata.locale_identifiers(): assert localedata.exists(l) + def test_unique_ids(): # Check all locale IDs are uniques. all_ids = localedata.locale_identifiers() @@ -93,6 +95,7 @@ def test_mixedcased_locale(): methodcaller(random.choice(['lower', 'upper']))(c) for c in l]) assert localedata.exists(locale_id) + def test_locale_argument_acceptance(): # Testing None input. normalized_locale = localedata.normalize_locale(None) @@ -105,3 +108,26 @@ def test_locale_argument_acceptance(): assert normalized_locale is None locale_exist = localedata.exists(['en_us', None]) assert locale_exist == False + + +def test_locale_identifiers_cache(monkeypatch): + original_listdir = localedata.os.listdir + listdir_calls = [] + def listdir_spy(*args): + rv = original_listdir(*args) + listdir_calls.append((args, rv)) + return rv + monkeypatch.setattr(localedata.os, 'listdir', listdir_spy) + + # In case we've already run some tests... + if hasattr(localedata.locale_identifiers, 'cache'): + del localedata.locale_identifiers.cache + + assert not listdir_calls + assert localedata.locale_identifiers() + assert len(listdir_calls) == 1 + assert localedata.locale_identifiers() is localedata.locale_identifiers.cache + assert len(listdir_calls) == 1 + localedata.locale_identifiers.cache = None + assert localedata.locale_identifiers() + assert len(listdir_calls) == 2 -- cgit v1.2.1