(root)/
Python-3.12.0/
Lib/
test/
test__locale.py
       1  from _locale import (setlocale, LC_ALL, LC_CTYPE, LC_NUMERIC, localeconv, Error)
       2  try:
       3      from _locale import (RADIXCHAR, THOUSEP, nl_langinfo)
       4  except ImportError:
       5      nl_langinfo = None
       6  
       7  import locale
       8  import sys
       9  import unittest
      10  from platform import uname
      11  
      12  from test import support
      13  
      14  if uname().system == "Darwin":
      15      maj, min, mic = [int(part) for part in uname().release.split(".")]
      16      if (maj, min, mic) < (8, 0, 0):
      17          raise unittest.SkipTest("locale support broken for OS X < 10.4")
      18  
      19  candidate_locales = ['es_UY', 'fr_FR', 'fi_FI', 'es_CO', 'pt_PT', 'it_IT',
      20      'et_EE', 'es_PY', 'no_NO', 'nl_NL', 'lv_LV', 'el_GR', 'be_BY', 'fr_BE',
      21      'ro_RO', 'ru_UA', 'ru_RU', 'es_VE', 'ca_ES', 'se_NO', 'es_EC', 'id_ID',
      22      'ka_GE', 'es_CL', 'wa_BE', 'hu_HU', 'lt_LT', 'sl_SI', 'hr_HR', 'es_AR',
      23      'es_ES', 'oc_FR', 'gl_ES', 'bg_BG', 'is_IS', 'mk_MK', 'de_AT', 'pt_BR',
      24      'da_DK', 'nn_NO', 'cs_CZ', 'de_LU', 'es_BO', 'sq_AL', 'sk_SK', 'fr_CH',
      25      'de_DE', 'sr_YU', 'br_FR', 'nl_BE', 'sv_FI', 'pl_PL', 'fr_CA', 'fo_FO',
      26      'bs_BA', 'fr_LU', 'kl_GL', 'fa_IR', 'de_BE', 'sv_SE', 'it_CH', 'uk_UA',
      27      'eu_ES', 'vi_VN', 'af_ZA', 'nb_NO', 'en_DK', 'tg_TJ', 'ps_AF', 'en_US',
      28      'fr_FR.ISO8859-1', 'fr_FR.UTF-8', 'fr_FR.ISO8859-15@euro',
      29      'ru_RU.KOI8-R', 'ko_KR.eucKR']
      30  
      31  def setUpModule():
      32      global candidate_locales
      33      # Issue #13441: Skip some locales (e.g. cs_CZ and hu_HU) on Solaris to
      34      # workaround a mbstowcs() bug. For example, on Solaris, the hu_HU locale uses
      35      # the locale encoding ISO-8859-2, the thousands separator is b'\xA0' and it is
      36      # decoded as U+30000020 (an invalid character) by mbstowcs().
      37      if sys.platform == 'sunos5':
      38          old_locale = locale.setlocale(locale.LC_ALL)
      39          try:
      40              locales = []
      41              for loc in candidate_locales:
      42                  try:
      43                      locale.setlocale(locale.LC_ALL, loc)
      44                  except Error:
      45                      continue
      46                  encoding = locale.getencoding()
      47                  try:
      48                      localeconv()
      49                  except Exception as err:
      50                      print("WARNING: Skip locale %s (encoding %s): [%s] %s"
      51                          % (loc, encoding, type(err), err))
      52                  else:
      53                      locales.append(loc)
      54              candidate_locales = locales
      55          finally:
      56              locale.setlocale(locale.LC_ALL, old_locale)
      57  
      58      # Workaround for MSVC6(debug) crash bug
      59      if "MSC v.1200" in sys.version:
      60          def accept(loc):
      61              a = loc.split(".")
      62              return not(len(a) == 2 and len(a[-1]) >= 9)
      63          candidate_locales = [loc for loc in candidate_locales if accept(loc)]
      64  
      65  # List known locale values to test against when available.
      66  # Dict formatted as ``<locale> : (<decimal_point>, <thousands_sep>)``.  If a
      67  # value is not known, use '' .
      68  known_numerics = {
      69      'en_US': ('.', ','),
      70      'de_DE' : (',', '.'),
      71      # The French thousands separator may be a breaking or non-breaking space
      72      # depending on the platform, so do not test it
      73      'fr_FR' : (',', ''),
      74      'ps_AF': ('\u066b', '\u066c'),
      75  }
      76  
      77  if sys.platform == 'win32':
      78      # ps_AF doesn't work on Windows: see bpo-38324 (msg361830)
      79      del known_numerics['ps_AF']
      80  
      81  class ESC[4;38;5;81m_LocaleTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      82  
      83      def setUp(self):
      84          self.oldlocale = setlocale(LC_ALL)
      85  
      86      def tearDown(self):
      87          setlocale(LC_ALL, self.oldlocale)
      88  
      89      # Want to know what value was calculated, what it was compared against,
      90      # what function was used for the calculation, what type of data was used,
      91      # the locale that was supposedly set, and the actual locale that is set.
      92      lc_numeric_err_msg = "%s != %s (%s for %s; set to %s, using %s)"
      93  
      94      def numeric_tester(self, calc_type, calc_value, data_type, used_locale):
      95          """Compare calculation against known value, if available"""
      96          try:
      97              set_locale = setlocale(LC_NUMERIC)
      98          except Error:
      99              set_locale = "<not able to determine>"
     100          known_value = known_numerics.get(used_locale,
     101                                      ('', ''))[data_type == 'thousands_sep']
     102          if known_value and calc_value:
     103              self.assertEqual(calc_value, known_value,
     104                                  self.lc_numeric_err_msg % (
     105                                      calc_value, known_value,
     106                                      calc_type, data_type, set_locale,
     107                                      used_locale))
     108              return True
     109  
     110      @unittest.skipUnless(nl_langinfo, "nl_langinfo is not available")
     111      @unittest.skipIf(
     112          support.is_emscripten or support.is_wasi,
     113          "musl libc issue on Emscripten, bpo-46390"
     114      )
     115      def test_lc_numeric_nl_langinfo(self):
     116          # Test nl_langinfo against known values
     117          tested = False
     118          for loc in candidate_locales:
     119              try:
     120                  setlocale(LC_NUMERIC, loc)
     121                  setlocale(LC_CTYPE, loc)
     122              except Error:
     123                  continue
     124              for li, lc in ((RADIXCHAR, "decimal_point"),
     125                              (THOUSEP, "thousands_sep")):
     126                  if self.numeric_tester('nl_langinfo', nl_langinfo(li), lc, loc):
     127                      tested = True
     128          if not tested:
     129              self.skipTest('no suitable locales')
     130  
     131      @unittest.skipIf(
     132          support.is_emscripten or support.is_wasi,
     133          "musl libc issue on Emscripten, bpo-46390"
     134      )
     135      def test_lc_numeric_localeconv(self):
     136          # Test localeconv against known values
     137          tested = False
     138          for loc in candidate_locales:
     139              try:
     140                  setlocale(LC_NUMERIC, loc)
     141                  setlocale(LC_CTYPE, loc)
     142              except Error:
     143                  continue
     144              formatting = localeconv()
     145              for lc in ("decimal_point",
     146                          "thousands_sep"):
     147                  if self.numeric_tester('localeconv', formatting[lc], lc, loc):
     148                      tested = True
     149          if not tested:
     150              self.skipTest('no suitable locales')
     151  
     152      @unittest.skipUnless(nl_langinfo, "nl_langinfo is not available")
     153      def test_lc_numeric_basic(self):
     154          # Test nl_langinfo against localeconv
     155          tested = False
     156          for loc in candidate_locales:
     157              try:
     158                  setlocale(LC_NUMERIC, loc)
     159                  setlocale(LC_CTYPE, loc)
     160              except Error:
     161                  continue
     162              for li, lc in ((RADIXCHAR, "decimal_point"),
     163                              (THOUSEP, "thousands_sep")):
     164                  nl_radixchar = nl_langinfo(li)
     165                  li_radixchar = localeconv()[lc]
     166                  try:
     167                      set_locale = setlocale(LC_NUMERIC)
     168                  except Error:
     169                      set_locale = "<not able to determine>"
     170                  self.assertEqual(nl_radixchar, li_radixchar,
     171                                  "%s (nl_langinfo) != %s (localeconv) "
     172                                  "(set to %s, using %s)" % (
     173                                                  nl_radixchar, li_radixchar,
     174                                                  loc, set_locale))
     175                  tested = True
     176          if not tested:
     177              self.skipTest('no suitable locales')
     178  
     179      def test_float_parsing(self):
     180          # Bug #1391872: Test whether float parsing is okay on European
     181          # locales.
     182          tested = False
     183          for loc in candidate_locales:
     184              try:
     185                  setlocale(LC_NUMERIC, loc)
     186                  setlocale(LC_CTYPE, loc)
     187              except Error:
     188                  continue
     189  
     190              # Ignore buggy locale databases. (Mac OS 10.4 and some other BSDs)
     191              if loc == 'eu_ES' and localeconv()['decimal_point'] == "' ":
     192                  continue
     193  
     194              self.assertEqual(int(eval('3.14') * 100), 314,
     195                                  "using eval('3.14') failed for %s" % loc)
     196              self.assertEqual(int(float('3.14') * 100), 314,
     197                                  "using float('3.14') failed for %s" % loc)
     198              if localeconv()['decimal_point'] != '.':
     199                  self.assertRaises(ValueError, float,
     200                                    localeconv()['decimal_point'].join(['1', '23']))
     201              tested = True
     202          if not tested:
     203              self.skipTest('no suitable locales')
     204  
     205  
     206  if __name__ == '__main__':
     207      unittest.main()