expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com --- pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
diff --git a/pyanaconda/localization.py b/pyanaconda/localization.py index acb3afd..26d53fd 100644 --- a/pyanaconda/localization.py +++ b/pyanaconda/localization.py @@ -19,9 +19,9 @@ # Red Hat Author(s): Martin Gracik mgracik@redhat.com #
-from collections import defaultdict, deque, OrderedDict +from collections import defaultdict, deque import gettext -import locale +import locale as locale_mod import os import re
@@ -33,6 +33,12 @@ LOCALE_PREFERENCES = {}
LOCALE_CONF_FILE_PATH = "/etc/locale.conf"
+#e.g. 'SR_RS.UTF-8@latin' +LANGCODE_RE = re.compile(r'(?P<language>[A-Za-z]+)' + r'(_(?P<territory>[A-Za-z]+))?' + r'(.(?P<codeset>[-\w]+))?' + r'(@(?P<modifier>[-\w]+))?') + class LocalizationConfigError(Exception): """Exception class for localization configuration related problems"""
@@ -194,6 +200,21 @@ def get_available_translations(domain=None, localedir=None): localeinfo = LocaleInfo(localedata, encoding, script) yield localeinfo
+def parse_langcode(langcode): + """ + For a given langcode (e.g. 'SR_RS.UTF-8@latin') returns a dictionary + with the following keys and example values: + + 'language' : 'SR' + 'territory' : 'RS' + 'codeset' : 'UTF-8' + 'modifier' : 'latin' + + """ + + match = LANGCODE_RE.match(langcode) + return match.groupdict() + def expand_langs(astring): """ Converts a single language into a "language search path". For example, @@ -207,37 +228,25 @@ def expand_langs(astring):
langs = set([astring])
- base = None - loc = None - encoding = None - script = None - - if "@" in astring: - (astring, script) = astring.split("@", 1) - - if "." in astring: - (astring, encoding) = astring.split(".", 1) - - if "_" in astring: - (astring, loc) = astring.split("_", 1) - - base = astring + lang_dict = parse_langcode(astring) + base, loc, enc, script = [lang_dict[key] for key in ("language", + "territory", "codeset", "modifier")]
if not base: return list(langs)
- if not encoding: - encoding = "UTF-8" + if not enc: + enc = "UTF-8"
langs.add(base) - langs.add("%s.%s" % (base, encoding)) + langs.add("%s.%s" % (base, enc))
if loc: langs.add("%s_%s" % (base, loc)) - langs.add("%s_%s.%s" %(base, loc, encoding)) + langs.add("%s_%s.%s" %(base, loc, enc)) if script: langs.add("%s@%s" % (base, script)) - langs.add("%s.%s@%s" % (base, encoding, script)) + langs.add("%s.%s@%s" % (base, enc, script))
if loc and script: langs.add("%s_%s@%s" % (base, loc, script)) @@ -308,13 +317,19 @@ class PreferredLocale(object): def __init__(self, localeset): self._localedict = {repr(locale):locale for locale in localeset}
- def get_all_locales(self, preferences=[]): + def get_all_locales(self, preferences=None): + if preferences is None: + preferences = [] preferences = filter(self._localedict.__contains__, preferences) - inside, outside = partition(self._localedict.keys(), func=lambda x: x in preferences) - sorted_locales = [self._localedict[localename] for localename in list(inside) + list(outside)] + inside, outside = partition(self._localedict.keys(), + func=lambda x: x in preferences) + sorted_locales = [self._localedict[localename] + for localename in list(inside) + list(outside)] return sorted_locales
- def get_preferred_locale(self, preferences=[]): + def get_preferred_locale(self, preferences=None): + if preferences is None: + preferences = [] try: return self.get_all_locales(preferences)[0] except IndexError: @@ -323,8 +338,12 @@ class PreferredLocale(object):
class Language(object):
- def __init__(self, preferences={}, territory=None): - self.translations = {repr(locale):locale for locale in get_available_translations()} + def __init__(self, preferences=None, territory=None): + if preferences is None: + preferences = {} + + self.translations = {repr(locale):locale + for locale in get_available_translations()} self.locales = {repr(locale):locale for locale in get_all_locales()} self.preferred_translation = self.translations[DEFAULT_LANG] self.preferred_locales = [self.locales[DEFAULT_LANG]] @@ -336,6 +355,8 @@ class Language(object): if self.territory: self._get_preferred_translation_and_locales()
+ self.install_lang = DEFAULT_LANG + self.system_lang = DEFAULT_LANG def _get_preferred_translation_and_locales(self): # get locales from territory locales_from_territory = PreferredLocale.from_territory(self.territory) @@ -381,19 +402,13 @@ class Language(object): # if territory is not set, use the one from preferred locale self.territory = self.territory or self.preferred_locale.territory
- @staticmethod - def parse_langcode(langcode): - pattern = re.compile(r'(?P<language>[A-Za-z]+)(_(?P<territory>[A-Za-z]+))?(.(?P<codeset>[-\w]+))?(@(?P<modifier>[-\w]+))?') - m = pattern.match(langcode) - return m.groupdict() - @property def install_lang_as_dict(self): - self.parse_langcode(self.install_lang) + parse_langcode(self.install_lang)
@property def system_lang_as_dict(self): - self.parse_langcode(self.system_lang) + parse_langcode(self.system_lang)
def set_install_lang(self, langcode): self.install_lang = langcode @@ -402,8 +417,8 @@ class Language(object): os.environ['LC_NUMERIC'] = 'C'
try: - locale.setlocale(locale.LC_ALL, '') - except locale.Error: + locale_mod.setlocale(locale_mod.LC_ALL, '') + except locale_mod.Error: pass
# XXX this is the sort of thing which you should never do,
On Tue, Jan 08, 2013 at 01:03:27PM +0100, Vratislav Podzimek wrote:
expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com
pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
- match = LANGCODE_RE.match(langcode)
- return match.groupdict()
The match could fail. I'd catch that and return an empty {}
- lang_dict = parse_langcode(astring)
- base, loc, enc, script = [lang_dict[key] for key in ("language",
"territory", "codeset", "modifier")]
The key may not be in the lang_dict, add 'if key in lang_dict' to the end of the list comprehension.
Looks good otherwise.
On Tue, 2013-01-08 at 09:22 -0800, Brian C. Lane wrote:
On Tue, Jan 08, 2013 at 01:03:27PM +0100, Vratislav Podzimek wrote:
expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com
pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
- match = LANGCODE_RE.match(langcode)
- return match.groupdict()
The match could fail. I'd catch that and return an empty {}
Good point, thanks! Fixing locally.
- lang_dict = parse_langcode(astring)
- base, loc, enc, script = [lang_dict[key] for key in ("language",
"territory", "codeset", "modifier")]
The key may not be in the lang_dict, add 'if key in lang_dict' to the end of the list comprehension.
The key has to be in dict if the dict is not {} (as suggested in your previous comment). Or am I wrong? I think check for lang_dict != {} should be enough. Using 'if key in lang_dict' doesn't make much sense to me as it would return the items in a wrong order in case something is missing.
On Wed, Jan 09, 2013 at 02:33:17PM +0100, Vratislav Podzimek wrote:
On Tue, 2013-01-08 at 09:22 -0800, Brian C. Lane wrote:
On Tue, Jan 08, 2013 at 01:03:27PM +0100, Vratislav Podzimek wrote:
expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com
pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
- match = LANGCODE_RE.match(langcode)
- return match.groupdict()
The match could fail. I'd catch that and return an empty {}
Good point, thanks! Fixing locally.
- lang_dict = parse_langcode(astring)
- base, loc, enc, script = [lang_dict[key] for key in ("language",
"territory", "codeset", "modifier")]
The key may not be in the lang_dict, add 'if key in lang_dict' to the end of the list comprehension.
The key has to be in dict if the dict is not {} (as suggested in your previous comment). Or am I wrong? I think check for lang_dict != {} should be enough. Using 'if key in lang_dict' doesn't make much sense to me as it would return the items in a wrong order in case something is missing.
I don't think we can guarantee that everything passed to parse_langcode will have all the right pieces. What does the regex do when only some of that matches? If it returns {} then sure, we don't need the extra check.
On Wed, 2013-01-09 at 06:36 -0800, Brian C. Lane wrote:
On Wed, Jan 09, 2013 at 02:33:17PM +0100, Vratislav Podzimek wrote:
On Tue, 2013-01-08 at 09:22 -0800, Brian C. Lane wrote:
On Tue, Jan 08, 2013 at 01:03:27PM +0100, Vratislav Podzimek wrote:
expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com
pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
- match = LANGCODE_RE.match(langcode)
- return match.groupdict()
The match could fail. I'd catch that and return an empty {}
Good point, thanks! Fixing locally.
- lang_dict = parse_langcode(astring)
- base, loc, enc, script = [lang_dict[key] for key in ("language",
"territory", "codeset", "modifier")]
The key may not be in the lang_dict, add 'if key in lang_dict' to the end of the list comprehension.
The key has to be in dict if the dict is not {} (as suggested in your previous comment). Or am I wrong? I think check for lang_dict != {} should be enough. Using 'if key in lang_dict' doesn't make much sense to me as it would return the items in a wrong order in case something is missing.
I don't think we can guarantee that everything passed to parse_langcode will have all the right pieces. What does the regex do when only some of that matches? If it returns {} then sure, we don't need the extra check.
The RE is written in a way that only the first (lang) part is required. The other parts are marked as optional and match.groupdict() puts None as values for those missing parts. So one or more of loc, enc and script may end up being None, but that's okay and shouldn't cause any troubles in the code following that assignment.
On Thu, Jan 10, 2013 at 10:48:03AM +0100, Vratislav Podzimek wrote:
On Wed, 2013-01-09 at 06:36 -0800, Brian C. Lane wrote:
On Wed, Jan 09, 2013 at 02:33:17PM +0100, Vratislav Podzimek wrote:
On Tue, 2013-01-08 at 09:22 -0800, Brian C. Lane wrote:
On Tue, Jan 08, 2013 at 01:03:27PM +0100, Vratislav Podzimek wrote:
expand_langs may use parse_langcode which should be a global function not a static method of the Language class. Also some pieces deserve better documentation and some other pieces were potentially dangerous.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com
pyanaconda/localization.py | 91 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-)
- match = LANGCODE_RE.match(langcode)
- return match.groupdict()
The match could fail. I'd catch that and return an empty {}
Good point, thanks! Fixing locally.
- lang_dict = parse_langcode(astring)
- base, loc, enc, script = [lang_dict[key] for key in ("language",
"territory", "codeset", "modifier")]
The key may not be in the lang_dict, add 'if key in lang_dict' to the end of the list comprehension.
The key has to be in dict if the dict is not {} (as suggested in your previous comment). Or am I wrong? I think check for lang_dict != {} should be enough. Using 'if key in lang_dict' doesn't make much sense to me as it would return the items in a wrong order in case something is missing.
I don't think we can guarantee that everything passed to parse_langcode will have all the right pieces. What does the regex do when only some of that matches? If it returns {} then sure, we don't need the extra check.
The RE is written in a way that only the first (lang) part is required. The other parts are marked as optional and match.groupdict() puts None as values for those missing parts. So one or more of loc, enc and script may end up being None, but that's okay and shouldn't cause any troubles in the code following that assignment.
Sounds good then.
anaconda-patches@lists.fedorahosted.org