From 6844ccc6da9fca94b51dd11623b32f05e805dcfa Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Wed, 2 Mar 2016 12:11:51 +0100 Subject: [PATCH 1/5] Test parsing of mixed-cased locale ID. --- tests/test_localedata.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_localedata.py b/tests/test_localedata.py index 80dd118c4..e8e91b317 100644 --- a/tests/test_localedata.py +++ b/tests/test_localedata.py @@ -13,6 +13,8 @@ import doctest import unittest +import random +from operator import methodcaller from babel import localedata @@ -73,6 +75,14 @@ def test_merge(): localedata.merge(d, {1: 'Foo', 2: 'Bar'}) assert d == {1: 'Foo', 2: 'Bar', 3: 'baz'} + def test_locale_identification(): for l in localedata.locale_identifiers(): assert localedata.exists(l) + + +def test_mixedcased_locale(): + for l in localedata.locale_identifiers(): + locale_id = ''.join([ + methodcaller(random.choice(['lower', 'upper']))(c) for c in l]) + assert localedata.exists(locale_id) From 3450a6747d85ee458b0c7ab20e1f195bb3f9effe Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Wed, 2 Mar 2016 13:01:37 +0100 Subject: [PATCH 2/5] Test locale IDs uniqueness. --- tests/test_localedata.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_localedata.py b/tests/test_localedata.py index e8e91b317..d0d92f61c 100644 --- a/tests/test_localedata.py +++ b/tests/test_localedata.py @@ -81,6 +81,15 @@ def test_locale_identification(): assert localedata.exists(l) +def test_unique_ids(): + # Check all locale IDs are uniques. + all_ids = localedata.locale_identifiers() + assert len(all_ids) == len(set(all_ids)) + # Check locale IDs don't collide after lower-case normalization. + lower_case_ids = list(map(methodcaller('lower'), all_ids)) + assert len(lower_case_ids) == len(set(lower_case_ids)) + + def test_mixedcased_locale(): for l in localedata.locale_identifiers(): locale_id = ''.join([ From 78eea4c158bfcd9f50205c7ffff08130dbb8286f Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Wed, 2 Mar 2016 17:04:13 +0100 Subject: [PATCH 3/5] Force normalization of locale ID. --- babel/localedata.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/babel/localedata.py b/babel/localedata.py index 437f49fae..a20a8813a 100644 --- a/babel/localedata.py +++ b/babel/localedata.py @@ -15,6 +15,7 @@ import os import threading from collections import MutableMapping +from itertools import chain from babel._compat import pickle @@ -24,15 +25,22 @@ _dirname = os.path.join(os.path.dirname(__file__), 'locale-data') +def normalize_locale(name): + """Return a normalized locale ID or `None` if the ID is not recognized.""" + name = name.strip().lower() + for locale_id in chain.from_iterable([_cache, locale_identifiers()]): + if name == locale_id.lower(): + return locale_id + + def exists(name): - """Check whether locale data is available for the given locale. Ther - return value is `True` if it exists, `False` otherwise. + """Check whether locale data is available for the given locale. + + Returns `True` if it exists, `False` otherwise. :param name: the locale identifier string """ - if name in _cache: - return True - return os.path.exists(os.path.join(_dirname, '%s.dat' % name)) + return True if normalize_locale(name) else False def locale_identifiers(): From a5cb8317626b71d532f78c8d86c6b0e790ad4b7f Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Thu, 3 Mar 2016 18:09:05 +0100 Subject: [PATCH 4/5] Explicit normalize_locale() documentation. --- babel/localedata.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/babel/localedata.py b/babel/localedata.py index a20a8813a..265e4b8fd 100644 --- a/babel/localedata.py +++ b/babel/localedata.py @@ -26,7 +26,11 @@ def normalize_locale(name): - """Return a normalized locale ID or `None` if the ID is not recognized.""" + """Normalize a locale ID by stripping spaces and apply proper casing. + + Returns the normalized locale ID string or `None` if the ID is not + recognized. + """ name = name.strip().lower() for locale_id in chain.from_iterable([_cache, locale_identifiers()]): if name == locale_id.lower(): From 1a6731e2b51747764199da40bb39fcb9354dfe58 Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Thu, 3 Mar 2016 18:17:44 +0100 Subject: [PATCH 5/5] Only attempt a normalization search if filesystem lookup fails. --- babel/localedata.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/babel/localedata.py b/babel/localedata.py index 265e4b8fd..1f4373798 100644 --- a/babel/localedata.py +++ b/babel/localedata.py @@ -44,7 +44,10 @@ def exists(name): :param name: the locale identifier string """ - return True if normalize_locale(name) else False + if name in _cache: + return True + file_found = os.path.exists(os.path.join(_dirname, '%s.dat' % name)) + return True if file_found else bool(normalize_locale(name)) def locale_identifiers():