issue 13441 skip some locales e g cscz and huhu on solaris to workaround a mbstowcs bug for example on solaris the huhu locale uses the locale encoding iso88592 the thousands separator is b xa0 and it is decoded as u30000020 an invalid character by mbstowcs workaround for msvc6debug crash bug list known locale values to test against when available dict formatted as locale decimalpoint thousandssep if a value is not known use the french thousands separator may be a breaking or nonbreaking space depending on the platform so do not test it psaf doesn t work on windows see bpo38324 msg361830 want to know what value was calculated what it was compared against what function was used for the calculation what type of data was used the locale that was supposedly set and the actual locale that is set compare calculation against known value if available try setlocale setlocalelcnumeric except error setlocale not able to determine knownvalue knownnumerics getusedlocale datatype thousandssep if knownvalue and calcvalue self assertequalcalcvalue knownvalue self lcnumericerrmsg calcvalue knownvalue calctype datatype setlocale usedlocale return true unittest skipunlessnllanginfo nllanginfo is not available unittest skipif support isemscripten or support iswasi musl libc issue on emscripten bpo46390 def testlcnumericnllanginfoself test nllanginfo against known values tested false for loc in candidatelocales try setlocalelcnumeric loc setlocalelcctype loc except error continue for li lc in radixchar decimalpoint thousep thousandssep if self numerictester nllanginfo nllanginfoli lc loc tested true if not tested self skiptest no suitable locales unittest skipif support isemscripten or support iswasi musl libc issue on emscripten bpo46390 def testlcnumericlocaleconvself test localeconv against known values tested false for loc in candidatelocales try setlocalelcnumeric loc setlocalelcctype loc except error continue formatting localeconv for lc in decimalpoint thousandssep if self numerictester localeconv formattinglc lc loc tested true if not tested self skiptest no suitable locales unittest skipunlessnllanginfo nllanginfo is not available def testlcnumericbasicself test nllanginfo against localeconv tested false for loc in candidatelocales try setlocalelcnumeric loc setlocalelcctype loc except error continue for li lc in radixchar decimalpoint thousep thousandssep nlradixchar nllanginfoli liradixchar localeconvlc try setlocale setlocalelcnumeric except error setlocale not able to determine self assertequalnlradixchar liradixchar s nllanginfo s localeconv set to s using s nlradixchar liradixchar loc setlocale tested true if not tested self skiptest no suitable locales def testfloatparsingself bug 1391872 test whether float parsing is okay on european locales tested false for loc in candidatelocales try setlocalelcnumeric loc setlocalelcctype loc except error continue ignore buggy locale databases mac os 10 4 and some other bsds if loc eues and localeconv decimalpoint continue self assertequalinteval 3 14 100 314 using eval 3 14 failed for s loc self assertequalintfloat 3 14 100 314 using float 3 14 failed for s loc if localeconv decimalpoint self assertraisesvalueerror float localeconv decimalpoint join 1 23 tested true if not tested self skiptest no suitable locales if name main unittest main issue 13441 skip some locales e g cs_cz and hu_hu on solaris to workaround a mbstowcs bug for example on solaris the hu_hu locale uses the locale encoding iso 8859 2 the thousands separator is b xa0 and it is decoded as u 30000020 an invalid character by mbstowcs workaround for msvc6 debug crash bug list known locale values to test against when available dict formatted as locale decimal_point thousands_sep if a value is not known use the french thousands separator may be a breaking or non breaking space depending on the platform so do not test it ps_af doesn t work on windows see bpo 38324 msg361830 want to know what value was calculated what it was compared against what function was used for the calculation what type of data was used the locale that was supposedly set and the actual locale that is set compare calculation against known value if available test nl_langinfo against known values test localeconv against known values test nl_langinfo against localeconv bug 1391872 test whether float parsing is okay on european locales ignore buggy locale databases mac os 10 4 and some other bsds
from _locale import (setlocale, LC_ALL, LC_CTYPE, LC_NUMERIC, localeconv, Error)
try:
    from _locale import (RADIXCHAR, THOUSEP, nl_langinfo)
except ImportError:
    nl_langinfo = None

import locale
import sys
import unittest
from platform import uname

from test import support

if uname().system == "Darwin":
    maj, min, mic = [int(part) for part in uname().release.split(".")]
    if (maj, min, mic) < (8, 0, 0):
        raise unittest.SkipTest("locale support broken for OS X < 10.4")

candidate_locales = ['es_UY', 'fr_FR', 'fi_FI', 'es_CO', 'pt_PT', 'it_IT',
    'et_EE', 'es_PY', 'no_NO', 'nl_NL', 'lv_LV', 'el_GR', 'be_BY', 'fr_BE',
    'ro_RO', 'ru_UA', 'ru_RU', 'es_VE', 'ca_ES', 'se_NO', 'es_EC', 'id_ID',
    'ka_GE', 'es_CL', 'wa_BE', 'hu_HU', 'lt_LT', 'sl_SI', 'hr_HR', 'es_AR',
    'es_ES', 'oc_FR', 'gl_ES', 'bg_BG', 'is_IS', 'mk_MK', 'de_AT', 'pt_BR',
    'da_DK', 'nn_NO', 'cs_CZ', 'de_LU', 'es_BO', 'sq_AL', 'sk_SK', 'fr_CH',
    'de_DE', 'sr_YU', 'br_FR', 'nl_BE', 'sv_FI', 'pl_PL', 'fr_CA', 'fo_FO',
    'bs_BA', 'fr_LU', 'kl_GL', 'fa_IR', 'de_BE', 'sv_SE', 'it_CH', 'uk_UA',
    'eu_ES', 'vi_VN', 'af_ZA', 'nb_NO', 'en_DK', 'tg_TJ', 'ps_AF', 'en_US',
    'fr_FR.ISO8859-1', 'fr_FR.UTF-8', 'fr_FR.ISO8859-15@euro',
    'ru_RU.KOI8-R', 'ko_KR.eucKR']

def setUpModule():
    global candidate_locales
    
    
    
    
    if sys.platform == 'sunos5':
        old_locale = locale.setlocale(locale.LC_ALL)
        try:
            locales = []
            for loc in candidate_locales:
                try:
                    locale.setlocale(locale.LC_ALL, loc)
                except Error:
                    continue
                encoding = locale.getencoding()
                try:
                    localeconv()
                except Exception as err:
                    print("WARNING: Skip locale %s (encoding %s): [%s] %s"
                        % (loc, encoding, type(err), err))
                else:
                    locales.append(loc)
            candidate_locales = locales
        finally:
            locale.setlocale(locale.LC_ALL, old_locale)

    
    if "MSC v.1200" in sys.version:
        def accept(loc):
            a = loc.split(".")
            return not(len(a) == 2 and len(a[-1]) >= 9)
        candidate_locales = [loc for loc in candidate_locales if accept(loc)]




known_numerics = {
    'en_US': ('.', ','),
    'de_DE' : (',', '.'),
    
    
    'fr_FR' : (',', ''),
    'ps_AF': ('\u066b', '\u066c'),
}

if sys.platform == 'win32':
    
    del known_numerics['ps_AF']

class _LocaleTests(unittest.TestCase):

    def setUp(self):
        self.oldlocale = setlocale(LC_ALL)

    def tearDown(self):
        setlocale(LC_ALL, self.oldlocale)

    
    
    
    lc_numeric_err_msg = "%s != %s (%s for %s; set to %s, using %s)"

    def numeric_tester(self, calc_type, calc_value, data_type, used_locale):
        
        try:
            set_locale = setlocale(LC_NUMERIC)
        except Error:
            set_locale = "<not able to determine>"
        known_value = known_numerics.get(used_locale,
                                    ('', ''))[data_type == 'thousands_sep']
        if known_value and calc_value:
            self.assertEqual(calc_value, known_value,
                                self.lc_numeric_err_msg % (
                                    calc_value, known_value,
                                    calc_type, data_type, set_locale,
                                    used_locale))
            return True

    @unittest.skipUnless(nl_langinfo, "nl_langinfo is not available")
    @unittest.skipIf(
        support.is_emscripten or support.is_wasi,
        "musl libc issue on Emscripten, bpo-46390"
    )
    def test_lc_numeric_nl_langinfo(self):
        
        tested = False
        for loc in candidate_locales:
            try:
                setlocale(LC_NUMERIC, loc)
                setlocale(LC_CTYPE, loc)
            except Error:
                continue
            for li, lc in ((RADIXCHAR, "decimal_point"),
                            (THOUSEP, "thousands_sep")):
                if self.numeric_tester('nl_langinfo', nl_langinfo(li), lc, loc):
                    tested = True
        if not tested:
            self.skipTest('no suitable locales')

    @unittest.skipIf(
        support.is_emscripten or support.is_wasi,
        "musl libc issue on Emscripten, bpo-46390"
    )
    def test_lc_numeric_localeconv(self):
        
        tested = False
        for loc in candidate_locales:
            try:
                setlocale(LC_NUMERIC, loc)
                setlocale(LC_CTYPE, loc)
            except Error:
                continue
            formatting = localeconv()
            for lc in ("decimal_point",
                        "thousands_sep"):
                if self.numeric_tester('localeconv', formatting[lc], lc, loc):
                    tested = True
        if not tested:
            self.skipTest('no suitable locales')

    @unittest.skipUnless(nl_langinfo, "nl_langinfo is not available")
    def test_lc_numeric_basic(self):
        
        tested = False
        for loc in candidate_locales:
            try:
                setlocale(LC_NUMERIC, loc)
                setlocale(LC_CTYPE, loc)
            except Error:
                continue
            for li, lc in ((RADIXCHAR, "decimal_point"),
                            (THOUSEP, "thousands_sep")):
                nl_radixchar = nl_langinfo(li)
                li_radixchar = localeconv()[lc]
                try:
                    set_locale = setlocale(LC_NUMERIC)
                except Error:
                    set_locale = "<not able to determine>"
                self.assertEqual(nl_radixchar, li_radixchar,
                                "%s (nl_langinfo) != %s (localeconv) "
                                "(set to %s, using %s)" % (
                                                nl_radixchar, li_radixchar,
                                                loc, set_locale))
                tested = True
        if not tested:
            self.skipTest('no suitable locales')

    def test_float_parsing(self):
        
        
        tested = False
        for loc in candidate_locales:
            try:
                setlocale(LC_NUMERIC, loc)
                setlocale(LC_CTYPE, loc)
            except Error:
                continue

            
            if loc == 'eu_ES' and localeconv()['decimal_point'] == "' ":
                continue

            self.assertEqual(int(eval('3.14') * 100), 314,
                                "using eval('3.14') failed for %s" % loc)
            self.assertEqual(int(float('3.14') * 100), 314,
                                "using float('3.14') failed for %s" % loc)
            if localeconv()['decimal_point'] != '.':
                self.assertRaises(ValueError, float,
                                  localeconv()['decimal_point'].join(['1', '23']))
            tested = True
        if not tested:
            self.skipTest('no suitable locales')


if __name__ == '__main__':
    unittest.main()