----- Original Message -----
From: "Vratislav Podzimek" <vpodzime(a)redhat.com>
To: anaconda-patches(a)lists.fedorahosted.org
Sent: Thursday, October 9, 2014 5:41:37 AM
Subject: [PATCH 1/2 v3] A function for resolving date format and order
It's not that easy to get right order of date fields (year, month, day) and
their formats so we should better have it in a standalone function with
tests.
Related: rhbz#1044233
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
pyanaconda/localization.py | 87
+++++++++++++++++++++++++++++
tests/pyanaconda_tests/localization_test.py | 17 ++++++
2 files changed, 104 insertions(+)
diff --git a/pyanaconda/localization.py b/pyanaconda/localization.py
index c95fa1d..2a2ed96 100644
--- a/pyanaconda/localization.py
+++ b/pyanaconda/localization.py
@@ -26,6 +26,7 @@ import re
import langtable
import locale as locale_mod
import glob
+from collections import namedtuple
from pyanaconda import constants
from pyanaconda.iutil import upcase_first_letter
@@ -469,3 +470,89 @@ def load_firmware_language(lang):
log.debug("Using UEFI PlatformLang '%s' ('%s') as our
language.", d,
locales[0])
setup_locale(locales[0], lang)
+
+_DateFieldSpec = namedtuple("DateFieldSpec", ["format",
"suffix"])
+
+def resolve_date_format(year, month, day, fail_safe=True):
+ """
+ Puts the year, month and day objects in the right order according to the
+ currently set locale and provides format specification for each of the
+ fields.
+
+ :param year: any object or value representing year
+ :type year: object
+ :param month: any object or value representing month
+ :type month: object
+ :param day: any object or value representing day
+ :type day: object
+ :param bool fail_safe: whether to fall back to default in case of
invalid
+ format or raise exception instead
+ :returns: a pair where the first field contains a tuple with the year,
month
+ and day objects/values put in the right order and where the
second
+ field contains a tuple with three :class:`_DateFieldSpec`
objects
+ specifying formats respectively to the first (year, month,
day)
+ field
+ :rtype: tuple
+ :raise ValueError: in case currently set locale has unsupported date
+ format and fail_safe is set to False
+
+ """
+
+ fail_safe_default = "%Y-%m-%d"
+
This looks like a should-be-capitalized constant.
+ def order_terms_formats(fmt_str):
+ # see date (1), 'O' (not '0') is a mystery, 'E' is
Buddhist
calendar, '(.*)'
+ # is an arbitrary suffix
+ field_spec_re = re.compile(r'([-_0OE^#]*)([yYmbBde])(.*)')
+
+ ordered_terms = []
+ ordered_formats = []
Please move these down to above the for loop that is their first use.
+ # see date (1)
+ fmt_str = fmt_str.replace("%F", "%Y-%m-%d")
+
+ # e.g. "%d.%m.%Y" -> ['d.', 'm.', 'Y']
+ fields = fmt_str.split("%")[1:]
+
+ for field in fields:
+ match = field_spec_re.match(field)
+ if not match:
+ # ignore fields we are not interested in (like %A for
weekday name, etc.)
+ continue
+
+ prefix, item, suffix = match.groups()
+ if item in ("d", "e"):
+ # "e" is the same as "_d"
+ ordered_terms.append(day)
+ elif item in ("Y", "y"):
+ # 4-digit year, 2-digit year
+ ordered_terms.append(year)
+ elif item in ("m", "b", "B"):
+ # month number, short month name, long month name
+ ordered_terms.append(month)
+
+ # "%" + prefix + item gives a format for date/time formatting
functions
+ ordered_formats.append(_DateFieldSpec("%" + prefix + item,
suffix.strip()))
+
+ if len(ordered_terms) != 3 or len(ordered_formats) != 3:
+ raise ValueError("Not all fields successfully identified in the
format '%s'" % fmt_str)
+
+ return (tuple(ordered_terms), tuple(ordered_formats))
+
+ fmt_str = locale_mod.nl_langinfo(locale_mod.D_FMT)
+
+ if not fmt_str or "%" not in fmt_str:
+ if fail_safe:
+ # use some sane default
+ fmt_str = fail_safe_default
+ else:
+ raise ValueError("Invalid date format string for current locale:
'%s'" % fmt_str)
+
+ try:
+ return order_terms_formats(fmt_str)
+ except ValueError:
+ if not fail_safe:
+ raise
+ else:
+ # if this call fails too, something is going terribly wrong and
we
+ # should be informed about it
+ return order_terms_formats(fail_safe_default)
diff --git a/tests/pyanaconda_tests/localization_test.py
b/tests/pyanaconda_tests/localization_test.py
index 00ff31d..521fb4a 100644
--- a/tests/pyanaconda_tests/localization_test.py
+++ b/tests/pyanaconda_tests/localization_test.py
@@ -19,6 +19,8 @@
#
from pyanaconda import localization
+from pyanaconda.iutil import execReadlines
+import locale as locale_mod
import unittest
class ParsingTests(unittest.TestCase):
@@ -139,3 +141,18 @@ class LangcodeLocaleMatchingTests(unittest.TestCase):
# no matches
self.assertIsNone(localization.find_best_locale_match("pt_BR",
["en_BR", "en"]))
self.assertIsNone(localization.find_best_locale_match("cs_CZ.UTF-8",
["en", "en.UTF-8"]))
+
+ def resolve_date_format_test(self):
+ """All locales' date formats should be properly
resolved."""
+
+ locales = (line.strip() for line in execReadlines("locale",
["-a"]))
+ for locale in locales:
+ try:
+ locale_mod.setlocale(locale_mod.LC_ALL, locale)
+ except locale_mod.Error:
+ # cannot set locale (a bug in the locale module?)
+ continue
+
+ (order, formats) = localization.resolve_date_format(1, 2, 3,
fail_safe=False)
+ for i in (1, 2, 3):
+ self.assertIn(i, order)
--
1.9.3
_______________________________________________
anaconda-patches mailing list
anaconda-patches(a)lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
Other than inline comments above, ack.
- mulhern