1- from test .support import verbose , is_android
1+ from decimal import Decimal
2+ from test .support import verbose , is_android , is_emscripten , is_wasi
23from test .support .warnings_helper import check_warnings
34import unittest
45import locale
@@ -140,18 +141,9 @@ class BaseFormattingTest(object):
140141 # Utility functions for formatting tests
141142 #
142143
143- def _test_formatfunc (self , format , value , out , func , ** format_opts ):
144- self .assertEqual (
145- func (format , value , ** format_opts ), out )
146-
147- def _test_format (self , format , value , out , ** format_opts ):
148- with check_warnings (('' , DeprecationWarning )):
149- self ._test_formatfunc (format , value , out ,
150- func = locale .format , ** format_opts )
151-
152144 def _test_format_string (self , format , value , out , ** format_opts ):
153- self ._test_formatfunc ( format , value , out ,
154- func = locale .format_string , ** format_opts )
145+ self .assertEqual (
146+ locale .format_string ( format , value , ** format_opts ), out )
155147
156148 def _test_currency (self , value , out , ** format_opts ):
157149 self .assertEqual (locale .currency (value , ** format_opts ), out )
@@ -165,48 +157,44 @@ def setUp(self):
165157 self .sep = locale .localeconv ()['thousands_sep' ]
166158
167159 def test_grouping (self ):
168- self ._test_format ("%f" , 1024 , grouping = 1 , out = '1%s024.000000' % self .sep )
169- self ._test_format ("%f" , 102 , grouping = 1 , out = '102.000000' )
170- self ._test_format ("%f" , - 42 , grouping = 1 , out = '-42.000000' )
171- self ._test_format ("%+f" , - 42 , grouping = 1 , out = '-42.000000' )
160+ self ._test_format_string ("%f" , 1024 , grouping = 1 , out = '1%s024.000000' % self .sep )
161+ self ._test_format_string ("%f" , 102 , grouping = 1 , out = '102.000000' )
162+ self ._test_format_string ("%f" , - 42 , grouping = 1 , out = '-42.000000' )
163+ self ._test_format_string ("%+f" , - 42 , grouping = 1 , out = '-42.000000' )
172164
173165 # TODO: RUSTPYTHON
174166 @unittest .expectedFailure
175167 def test_grouping_and_padding (self ):
176- self ._test_format ("%20.f" , - 42 , grouping = 1 , out = '-42' .rjust (20 ))
168+ self ._test_format_string ("%20.f" , - 42 , grouping = 1 , out = '-42' .rjust (20 ))
177169 if self .sep :
178- self ._test_format ("%+10.f" , - 4200 , grouping = 1 ,
170+ self ._test_format_string ("%+10.f" , - 4200 , grouping = 1 ,
179171 out = ('-4%s200' % self .sep ).rjust (10 ))
180- self ._test_format ("%-10.f" , - 4200 , grouping = 1 ,
172+ self ._test_format_string ("%-10.f" , - 4200 , grouping = 1 ,
181173 out = ('-4%s200' % self .sep ).ljust (10 ))
182174
183175 def test_integer_grouping (self ):
184- self ._test_format ("%d" , 4200 , grouping = True , out = '4%s200' % self .sep )
185- self ._test_format ("%+d" , 4200 , grouping = True , out = '+4%s200' % self .sep )
186- self ._test_format ("%+d" , - 4200 , grouping = True , out = '-4%s200' % self .sep )
176+ self ._test_format_string ("%d" , 4200 , grouping = True , out = '4%s200' % self .sep )
177+ self ._test_format_string ("%+d" , 4200 , grouping = True , out = '+4%s200' % self .sep )
178+ self ._test_format_string ("%+d" , - 4200 , grouping = True , out = '-4%s200' % self .sep )
187179
188180 def test_integer_grouping_and_padding (self ):
189- self ._test_format ("%10d" , 4200 , grouping = True ,
181+ self ._test_format_string ("%10d" , 4200 , grouping = True ,
190182 out = ('4%s200' % self .sep ).rjust (10 ))
191- self ._test_format ("%-10d" , - 4200 , grouping = True ,
183+ self ._test_format_string ("%-10d" , - 4200 , grouping = True ,
192184 out = ('-4%s200' % self .sep ).ljust (10 ))
193185
194186 def test_simple (self ):
195- self ._test_format ("%f" , 1024 , grouping = 0 , out = '1024.000000' )
196- self ._test_format ("%f" , 102 , grouping = 0 , out = '102.000000' )
197- self ._test_format ("%f" , - 42 , grouping = 0 , out = '-42.000000' )
198- self ._test_format ("%+f" , - 42 , grouping = 0 , out = '-42.000000' )
187+ self ._test_format_string ("%f" , 1024 , grouping = 0 , out = '1024.000000' )
188+ self ._test_format_string ("%f" , 102 , grouping = 0 , out = '102.000000' )
189+ self ._test_format_string ("%f" , - 42 , grouping = 0 , out = '-42.000000' )
190+ self ._test_format_string ("%+f" , - 42 , grouping = 0 , out = '-42.000000' )
199191
200192 # TODO: RUSTPYTHON
201193 @unittest .expectedFailure
202194 def test_padding (self ):
203- self ._test_format ("%20.f" , - 42 , grouping = 0 , out = '-42' .rjust (20 ))
204- self ._test_format ("%+10.f" , - 4200 , grouping = 0 , out = '-4200' .rjust (10 ))
205- self ._test_format ("%-10.f" , 4200 , grouping = 0 , out = '4200' .ljust (10 ))
206-
207- def test_format_deprecation (self ):
208- with self .assertWarns (DeprecationWarning ):
209- locale .format ("%-10.f" , 4200 , grouping = True )
195+ self ._test_format_string ("%20.f" , - 42 , grouping = 0 , out = '-42' .rjust (20 ))
196+ self ._test_format_string ("%+10.f" , - 4200 , grouping = 0 , out = '-4200' .rjust (10 ))
197+ self ._test_format_string ("%-10.f" , 4200 , grouping = 0 , out = '4200' .ljust (10 ))
210198
211199 def test_complex_formatting (self ):
212200 # Spaces in formatting string
@@ -233,20 +221,9 @@ def test_complex_formatting(self):
233221 out = 'int 1%s000 float 1%s000.00 str str' %
234222 (self .sep , self .sep ))
235223
236-
237- class TestFormatPatternArg (unittest .TestCase ):
238- # Test handling of pattern argument of format
239-
240- def test_onlyOnePattern (self ):
241- with check_warnings (('' , DeprecationWarning )):
242- # Issue 2522: accept exactly one % pattern, and no extra chars.
243- self .assertRaises (ValueError , locale .format , "%f\n " , 'foo' )
244- self .assertRaises (ValueError , locale .format , "%f\r " , 'foo' )
245- self .assertRaises (ValueError , locale .format , "%f\r \n " , 'foo' )
246- self .assertRaises (ValueError , locale .format , " %f" , 'foo' )
247- self .assertRaises (ValueError , locale .format , "%fg" , 'foo' )
248- self .assertRaises (ValueError , locale .format , "%^g" , 'foo' )
249- self .assertRaises (ValueError , locale .format , "%f%%" , 'foo' )
224+ self ._test_format_string ("total=%i%%" , 100 , out = 'total=100%' )
225+ self ._test_format_string ("newline: %i\n " , 3 , out = 'newline: 3\n ' )
226+ self ._test_format_string ("extra: %ii" , 3 , out = 'extra: 3i' )
250227
251228
252229class TestLocaleFormatString (unittest .TestCase ):
@@ -295,52 +272,51 @@ class TestCNumberFormatting(CCookedTest, BaseFormattingTest):
295272 # Test number formatting with a cooked "C" locale.
296273
297274 def test_grouping (self ):
298- self ._test_format ("%.2f" , 12345.67 , grouping = True , out = '12345.67' )
275+ self ._test_format_string ("%.2f" , 12345.67 , grouping = True , out = '12345.67' )
299276
300277 def test_grouping_and_padding (self ):
301- self ._test_format ("%9.2f" , 12345.67 , grouping = True , out = ' 12345.67' )
278+ self ._test_format_string ("%9.2f" , 12345.67 , grouping = True , out = ' 12345.67' )
302279
303280
304281class TestFrFRNumberFormatting (FrFRCookedTest , BaseFormattingTest ):
305282 # Test number formatting with a cooked "fr_FR" locale.
306283
307284 def test_decimal_point (self ):
308- self ._test_format ("%.2f" , 12345.67 , out = '12345,67' )
285+ self ._test_format_string ("%.2f" , 12345.67 , out = '12345,67' )
309286
310287 def test_grouping (self ):
311- self ._test_format ("%.2f" , 345.67 , grouping = True , out = '345,67' )
312- self ._test_format ("%.2f" , 12345.67 , grouping = True , out = '12 345,67' )
288+ self ._test_format_string ("%.2f" , 345.67 , grouping = True , out = '345,67' )
289+ self ._test_format_string ("%.2f" , 12345.67 , grouping = True , out = '12 345,67' )
313290
314291 def test_grouping_and_padding (self ):
315- self ._test_format ("%6.2f" , 345.67 , grouping = True , out = '345,67' )
316- self ._test_format ("%7.2f" , 345.67 , grouping = True , out = ' 345,67' )
317- self ._test_format ("%8.2f" , 12345.67 , grouping = True , out = '12 345,67' )
318- self ._test_format ("%9.2f" , 12345.67 , grouping = True , out = '12 345,67' )
319- self ._test_format ("%10.2f" , 12345.67 , grouping = True , out = ' 12 345,67' )
320- self ._test_format ("%-6.2f" , 345.67 , grouping = True , out = '345,67' )
321- self ._test_format ("%-7.2f" , 345.67 , grouping = True , out = '345,67 ' )
322- self ._test_format ("%-8.2f" , 12345.67 , grouping = True , out = '12 345,67' )
323- self ._test_format ("%-9.2f" , 12345.67 , grouping = True , out = '12 345,67' )
324- self ._test_format ("%-10.2f" , 12345.67 , grouping = True , out = '12 345,67 ' )
292+ self ._test_format_string ("%6.2f" , 345.67 , grouping = True , out = '345,67' )
293+ self ._test_format_string ("%7.2f" , 345.67 , grouping = True , out = ' 345,67' )
294+ self ._test_format_string ("%8.2f" , 12345.67 , grouping = True , out = '12 345,67' )
295+ self ._test_format_string ("%9.2f" , 12345.67 , grouping = True , out = '12 345,67' )
296+ self ._test_format_string ("%10.2f" , 12345.67 , grouping = True , out = ' 12 345,67' )
297+ self ._test_format_string ("%-6.2f" , 345.67 , grouping = True , out = '345,67' )
298+ self ._test_format_string ("%-7.2f" , 345.67 , grouping = True , out = '345,67 ' )
299+ self ._test_format_string ("%-8.2f" , 12345.67 , grouping = True , out = '12 345,67' )
300+ self ._test_format_string ("%-9.2f" , 12345.67 , grouping = True , out = '12 345,67' )
301+ self ._test_format_string ("%-10.2f" , 12345.67 , grouping = True , out = '12 345,67 ' )
325302
326303 def test_integer_grouping (self ):
327- self ._test_format ("%d" , 200 , grouping = True , out = '200' )
328- self ._test_format ("%d" , 4200 , grouping = True , out = '4 200' )
304+ self ._test_format_string ("%d" , 200 , grouping = True , out = '200' )
305+ self ._test_format_string ("%d" , 4200 , grouping = True , out = '4 200' )
329306
330307 def test_integer_grouping_and_padding (self ):
331- self ._test_format ("%4d" , 4200 , grouping = True , out = '4 200' )
332- self ._test_format ("%5d" , 4200 , grouping = True , out = '4 200' )
333- self ._test_format ("%10d" , 4200 , grouping = True , out = '4 200' .rjust (10 ))
334- self ._test_format ("%-4d" , 4200 , grouping = True , out = '4 200' )
335- self ._test_format ("%-5d" , 4200 , grouping = True , out = '4 200' )
336- self ._test_format ("%-10d" , 4200 , grouping = True , out = '4 200' .ljust (10 ))
308+ self ._test_format_string ("%4d" , 4200 , grouping = True , out = '4 200' )
309+ self ._test_format_string ("%5d" , 4200 , grouping = True , out = '4 200' )
310+ self ._test_format_string ("%10d" , 4200 , grouping = True , out = '4 200' .rjust (10 ))
311+ self ._test_format_string ("%-4d" , 4200 , grouping = True , out = '4 200' )
312+ self ._test_format_string ("%-5d" , 4200 , grouping = True , out = '4 200' )
313+ self ._test_format_string ("%-10d" , 4200 , grouping = True , out = '4 200' .ljust (10 ))
337314
338315 def test_currency (self ):
339316 euro = '\u20ac '
340317 self ._test_currency (50000 , "50000,00 " + euro )
341318 self ._test_currency (50000 , "50 000,00 " + euro , grouping = True )
342- # XXX is the trailing space a bug?
343- self ._test_currency (50000 , "50 000,00 EUR " ,
319+ self ._test_currency (50000 , "50 000,00 EUR" ,
344320 grouping = True , international = True )
345321
346322
@@ -371,7 +347,7 @@ class TestEnUSCollation(BaseLocalizedTest, TestCollation):
371347 locale_type = locale .LC_ALL
372348
373349 def setUp (self ):
374- enc = codecs .lookup (locale .getpreferredencoding ( False ) or 'ascii' ).name
350+ enc = codecs .lookup (locale .getencoding ( ) or 'ascii' ).name
375351 if enc not in ('utf-8' , 'iso8859-1' , 'cp1252' ):
376352 raise unittest .SkipTest ('encoding not suitable' )
377353 if enc != 'iso8859-1' and (sys .platform == 'darwin' or is_android or
@@ -381,11 +357,19 @@ def setUp(self):
381357
382358 @unittest .skipIf (sys .platform .startswith ('aix' ),
383359 'bpo-29972: broken test on AIX' )
360+ @unittest .skipIf (
361+ is_emscripten or is_wasi ,
362+ "musl libc issue on Emscripten/WASI, bpo-46390"
363+ )
384364 def test_strcoll_with_diacritic (self ):
385365 self .assertLess (locale .strcoll ('à' , 'b' ), 0 )
386366
387367 @unittest .skipIf (sys .platform .startswith ('aix' ),
388368 'bpo-29972: broken test on AIX' )
369+ @unittest .skipIf (
370+ is_emscripten or is_wasi ,
371+ "musl libc issue on Emscripten/WASI, bpo-46390"
372+ )
389373 def test_strxfrm_with_diacritic (self ):
390374 self .assertLess (locale .strxfrm ('à' ), locale .strxfrm ('b' ))
391375
@@ -506,7 +490,7 @@ class TestMiscellaneous(unittest.TestCase):
506490 @unittest .expectedFailure
507491 def test_defaults_UTF8 (self ):
508492 # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is
509- # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing
493+ # valid. Furthermore LC_CTYPE=UTF is used by the UTF-8 locale coercing
510494 # during interpreter startup (on macOS).
511495 import _locale
512496 import os
@@ -528,7 +512,8 @@ def test_defaults_UTF8(self):
528512
529513 os .environ ['LC_CTYPE' ] = 'UTF-8'
530514
531- self .assertEqual (locale .getdefaultlocale (), (None , 'UTF-8' ))
515+ with check_warnings (('' , DeprecationWarning )):
516+ self .assertEqual (locale .getdefaultlocale (), (None , 'UTF-8' ))
532517
533518 finally :
534519 for k in orig_env :
@@ -540,6 +525,14 @@ def test_defaults_UTF8(self):
540525 if orig_getlocale is not None :
541526 _locale ._getdefaultlocale = orig_getlocale
542527
528+ def test_getencoding (self ):
529+ # Invoke getencoding to make sure it does not cause exceptions.
530+ enc = locale .getencoding ()
531+ self .assertIsInstance (enc , str )
532+ self .assertNotEqual (enc , "" )
533+ # make sure it is valid
534+ codecs .lookup (enc )
535+
543536 def test_getpreferredencoding (self ):
544537 # Invoke getpreferredencoding to make sure it does not cause exceptions.
545538 enc = locale .getpreferredencoding ()
@@ -577,7 +570,13 @@ def test_getsetlocale_issue1813(self):
577570 loc = locale .getlocale (locale .LC_CTYPE )
578571 if verbose :
579572 print ('testing with %a' % (loc ,), end = ' ' , flush = True )
580- locale .setlocale (locale .LC_CTYPE , loc )
573+ try :
574+ locale .setlocale (locale .LC_CTYPE , loc )
575+ except locale .Error as exc :
576+ # bpo-37945: setlocale(LC_CTYPE) fails with getlocale(LC_CTYPE)
577+ # and the tr_TR locale on Windows. getlocale() builds a locale
578+ # which is not recognize by setlocale().
579+ self .skipTest (f"setlocale(LC_CTYPE, { loc !r} ) failed: { exc !r} " )
581580 self .assertEqual (loc , locale .getlocale (locale .LC_CTYPE ))
582581
583582 def test_invalid_locale_format_in_localetuple (self ):
@@ -643,5 +642,32 @@ def test_atoi(self):
643642 self ._test_atoi ('50 000' , 50000 )
644643
645644
645+ class BaseLocalizeTest (BaseLocalizedTest ):
646+
647+ def _test_localize (self , value , out , grouping = False ):
648+ self .assertEqual (locale .localize (value , grouping = grouping ), out )
649+
650+
651+ class TestEnUSLocalize (EnUSCookedTest , BaseLocalizeTest ):
652+
653+ def test_localize (self ):
654+ self ._test_localize ('50000.00' , '50000.00' )
655+ self ._test_localize (
656+ '{0:.16f}' .format (Decimal ('1.15' )), '1.1500000000000000' )
657+
658+
659+ class TestCLocalize (CCookedTest , BaseLocalizeTest ):
660+
661+ def test_localize (self ):
662+ self ._test_localize ('50000.00' , '50000.00' )
663+
664+
665+ class TestfrFRLocalize (FrFRCookedTest , BaseLocalizeTest ):
666+
667+ def test_localize (self ):
668+ self ._test_localize ('50000.00' , '50000,00' )
669+ self ._test_localize ('50000.00' , '50 000,00' , grouping = True )
670+
671+
646672if __name__ == '__main__' :
647673 unittest .main ()
0 commit comments