base class for tests using a real locale the locale test work fine on osx 10 6 i ronaldoussoren haven t had time yet to verify if tests work on osx 10 5 10 4 is known to be bad base class for tests using cooked localeconv values a cooked c locale a cooked enus locale a cooked frfr locale with a space character as decimal separator and a nonascii currency symbol utility functions for formatting tests xxx there is a grouping padding bug when the thousands separator is empty but the grouping array contains values e g solaris 10 spaces in formatting string dots in formatting string padding asterisk formats test moreinone general tests on locale formatstring def testpercentescapeself self assertequallocale formatstring f 1 0 f 1 0 self assertequallocale formatstring d fd 1 1 0 d fd 1 1 0 self assertequallocale formatstring foos d foo bar foos d foo bar def testmappingself self assertequallocale formatstring foos bing foo bar foos bing foo bar self assertequallocale formatstring foos foo bar foos foo bar class testnumberformattingbaselocalizedtest enusnumberformatting test number formatting with a real english locale localetype locale lcnumeric def setupself baselocalizedtest setupself enusnumberformatting setupself class testenusnumberformattingenuscookedtest enusnumberformatting test number formatting with a cooked enus locale def setupself enuscookedtest setupself enusnumberformatting setupself def testcurrencyself self testcurrency50000 50000 00 self testcurrency50000 50 000 00 groupingtrue self testcurrency50000 usd 50 000 00 groupingtrue internationaltrue class testcnumberformattingccookedtest baseformattingtest test number formatting with a cooked c locale def testgroupingself self testformatstring 2f 12345 67 groupingtrue out 12345 67 def testgroupingandpaddingself self testformatstring9 2f 12345 67 groupingtrue out 12345 67 class testfrfrnumberformattingfrfrcookedtest baseformattingtest test number formatting with a cooked frfr locale def testdecimalpointself self testformatstring 2f 12345 67 out 12345 67 def testgroupingself self testformatstring 2f 345 67 groupingtrue out 345 67 self testformatstring 2f 12345 67 groupingtrue out 12 345 67 def testgroupingandpaddingself self testformatstring6 2f 345 67 groupingtrue out 345 67 self testformatstring7 2f 345 67 groupingtrue out 345 67 self testformatstring8 2f 12345 67 groupingtrue out 12 345 67 self testformatstring9 2f 12345 67 groupingtrue out 12 345 67 self testformatstring10 2f 12345 67 groupingtrue out 12 345 67 self testformatstring6 2f 345 67 groupingtrue out 345 67 self testformatstring7 2f 345 67 groupingtrue out 345 67 self testformatstring8 2f 12345 67 groupingtrue out 12 345 67 self testformatstring9 2f 12345 67 groupingtrue out 12 345 67 self testformatstring10 2f 12345 67 groupingtrue out 12 345 67 def testintegergroupingself self testformatstringd 200 groupingtrue out 200 self testformatstringd 4200 groupingtrue out 4 200 def testintegergroupingandpaddingself self testformatstring4d 4200 groupingtrue out 4 200 self testformatstring5d 4200 groupingtrue out 4 200 self testformatstring10d 4200 groupingtrue out 4 200 rjust10 self testformatstring4d 4200 groupingtrue out 4 200 self testformatstring5d 4200 groupingtrue out 4 200 self testformatstring10d 4200 groupingtrue out 4 200 ljust10 def testcurrencyself euro u20ac self testcurrency50000 50000 00 euro self testcurrency50000 50 000 00 euro groupingtrue self testcurrency50000 50 000 00 eur groupingtrue internationaltrue class testcollationunittest testcase test string collation functions def teststrcollself self assertlesslocale strcoll a b 0 self assertequallocale strcoll a a 0 self assertgreaterlocale strcoll b a 0 embedded null character self assertraisesvalueerror locale strcoll a0 a self assertraisesvalueerror locale strcoll a a0 def teststrxfrmself self assertlesslocale strxfrm a locale strxfrm b embedded null character self assertraisesvalueerror locale strxfrm a0 class testenuscollationbaselocalizedtest testcollation test string collation functions with a real english locale localetype locale lcall def setupself enc codecs lookuplocale getencoding or ascii name if enc not in utf8 iso88591 cp1252 raise unittest skiptest encoding not suitable if enc iso88591 and sys platform darwin or isandroid or sys platform startswith freebsd raise unittest skiptest wcscollwcsxfrm have known bugs baselocalizedtest setupself unittest skipifsys platform startswith aix bpo29972 broken test on aix unittest skipif isemscripten or iswasi musl libc issue on emscriptenwasi bpo46390 def teststrcollwithdiacriticself self assertlesslocale strcoll b 0 unittest skipifsys platform startswith aix bpo29972 broken test on aix unittest skipif isemscripten or iswasi musl libc issue on emscriptenwasi bpo46390 def teststrxfrmwithdiacriticself self assertlesslocale strxfrm locale strxfrm b class normalizetestunittest testcase def checkself localename expected self assertequallocale normalizelocalename expected msglocalename def testlocalealiasself for localename alias in locale localealias items with self subtestlocalelocalename alias self checklocalename alias def testemptyself self check def testcself self check c c self check posix c def testenglishself self check en enus iso88591 self check en enus iso88591 self check en iso88591 enus iso88591 self check enus enus iso88591 self check enus enus iso88591 self check engb engb iso88591 self check enus utf8 enus utf8 self check enus utf8 enus utf8 self check enus utf8 enus utf8 self check enus iso88591 enus iso88591 self check enus usascii enus iso88591 self check enus 88591 enus iso88591 self check enus 885915 enus iso885915 self check english enen iso88591 self check englishuk ascii engb iso88591 def testhyphenatedencodingself self check azaz iso88599e azaz iso88599e self check azaz iso88599e azaz iso88599e self check ttru koi8c ttru koi8c self check ttru koi8c ttru koi8c self check lola cp1133 lola ibmcp1133 self check lola ibmcp1133 lola ibmcp1133 self check lola ibmcp1133 lola ibmcp1133 self check ukua microsoftcp1251 ukua cp1251 self check ukua microsoftcp1251 ukua cp1251 self check kage georgianacademy kage georgianacademy self check kage georgianacademy kage georgianacademy self check cscz iso88592 cscz iso88592 self check cscz iso88592 cscz iso88592 def testeuromodifierself self check dedeeuro dede iso885915 self check enus iso885915euro enus iso885915 self check dede utf8euro dede utf8 def testlatinmodifierself self check beby utf8latin beby utf8latin self check srrs utf8latin srrs utf8latin self check srrs utf8latn srrs utf8latin def testvalenciamodifierself self check caes utf8valencia caes utf8valencia self check caesvalencia caes utf8valencia self check cavalencia caes iso88591valencia def testdevanagarimodifierself self check ksin utf8devanagari ksin utf8devanagari self check ksindevanagari ksin utf8devanagari self check ksdevanagari ksin utf8devanagari self check ksin utf8 ksin utf8 self check ksin ksin utf8 self check ks ksin utf8 self check sdin utf8devanagari sdin utf8devanagari self check sdindevanagari sdin utf8devanagari self check sddevanagari sdin utf8devanagari self check sdin utf8 sdin utf8 self check sdin sdin utf8 self check sd sdin utf8 def testeucencodingself self check jajp euc jajp eucjp self check jajp eucjp jajp eucjp self check kokr euc kokr euckr self check kokr euckr kokr euckr self check zhcn euc zhcn euccn self check zhtw euc zhtw euctw self check zhtw euctw zhtw euctw def testjapaneseself self check ja jajp eucjp self check ja jis jajp jis7 self check ja sjis jajp sjis self check jajp jajp eucjp self check jajp ajec jajp eucjp self check jajp euc jajp eucjp self check jajp eucjp jajp eucjp self check jajp iso2022jp jajp jis7 self check jajp iso2022jp jajp jis7 self check jajp jis jajp jis7 self check jajp jis7 jajp jis7 self check jajp mscode jajp sjis self check jajp pck jajp sjis self check jajp sjis jajp sjis self check jajp ujis jajp eucjp self check jajp utf8 jajp utf8 self check japan jajp eucjp self check japanese jajp eucjp self check japaneseeuc jajp eucjp self check japanese euc jajp eucjp self check japanese sjis jajp sjis self check jpjp jajp eucjp class testmiscellaneousunittest testcase def testdefaultsutf8self issue 18378 on at least macos setting lcctype to utf8 is valid furthermore lcctypeutf is used by the utf8 locale coercing during interpreter startup on macos import locale import os self assertequallocale parselocalename utf8 none utf8 if hasattrlocale getdefaultlocale origgetlocale locale getdefaultlocale del locale getdefaultlocale else origgetlocale none origenv try for key in lcall lcctype lang language if key in os environ origenvkey os environkey del os environkey os environ lcctype utf8 with checkwarnings deprecationwarning self assertequallocale getdefaultlocale none utf8 finally for k in origenv os environk origenvk if lcctype not in origenv del os environ lcctype if origgetlocale is not none locale getdefaultlocale origgetlocale def testgetencodingself invoke getencoding to make sure it does not cause exceptions enc locale getencoding self assertisinstanceenc str self assertnotequalenc make sure it is valid codecs lookupenc def testgetencodingfallbackself when locale getencoding is missing locale getencoding uses the python filesystem encoding fallbackencoding with mock patch objectsys getfilesystemencoding returnvalueencoding localefallback importfreshmodule locale blocked locale self assertequallocalefallback getencoding encoding def testgetpreferredencodingself invoke getpreferredencoding to make sure it does not cause exceptions enc locale getpreferredencoding if enc if encoding nonempty make sure it is valid codecs lookupenc def teststrcoll3303self test crasher from bug 3303 self assertraisestypeerror locale strcoll a none self assertraisestypeerror locale strcoll ba none def testsetlocalecategoryself locale setlocalelocale lcall locale setlocalelocale lctime locale setlocalelocale lcctype locale setlocalelocale lccollate locale setlocalelocale lcmonetary locale setlocalelocale lcnumeric crasher from bug 7419 self assertraiseslocale error locale setlocale 12345 def testgetsetlocaleissue1813self issue 1813 setting and getting the locale under a turkish locale oldlocale locale setlocalelocale lcctype self addcleanuplocale setlocale locale lcctype oldlocale try locale setlocalelocale lcctype trtr except locale error unsupported locale on this system self skiptest test needs turkish locale loc locale getlocalelocale lcctype if verbose print testing with a loc end flushtrue try locale setlocalelocale lcctype loc except locale error as exc bpo37945 setlocalelcctype fails with getlocalelcctype and the trtr locale on windows getlocale builds a locale which is not recognize by setlocale self skiptestfsetlocalelcctype loc r failed exc r self assertequalloc locale getlocalelocale lcctype def testinvalidlocaleformatinlocaletupleself with self assertraisestypeerror locale setlocalelocale lcall b fifi def testinvaliditerableinlocaletupleself with self assertraisestypeerror locale setlocalelocale lcall b not b valid class basedelocalizetestbaselocalizedtest def testdelocalizeself value out self assertequallocale delocalizevalue out def testatofself value out self assertequallocale atofvalue out def testatoiself value out self assertequallocale atoivalue out class testenusdelocalizeenuscookedtest basedelocalizetest def testdelocalizeself self testdelocalize 50000 00 50000 00 self testdelocalize 50 000 00 50000 00 def testatofself self testatof 50000 00 50000 self testatof 50 000 00 50000 def testatoiself self testatoi 50000 50000 self testatoi 50 000 50000 class testcdelocalizetestccookedtest basedelocalizetest def testdelocalizeself self testdelocalize 50000 00 50000 00 def testatofself self testatof 50000 00 50000 def testatoiself self testatoi 50000 50000 class testfrfrdelocalizetestfrfrcookedtest basedelocalizetest def testdelocalizeself self testdelocalize 50000 00 50000 00 self testdelocalize 50 000 00 50000 00 def testatofself self testatof 50000 00 50000 self testatof 50 000 00 50000 def testatoiself self testatoi 50000 50000 self testatoi 50 000 50000 class baselocalizetestbaselocalizedtest def testlocalizeself value out groupingfalse self assertequallocale localizevalue groupinggrouping out class testenuslocalizeenuscookedtest baselocalizetest def testlocalizeself self testlocalize 50000 00 50000 00 self testlocalize 0 16f formatdecimal 1 15 1 1500000000000000 class testclocalizeccookedtest baselocalizetest def testlocalizeself self testlocalize 50000 00 50000 00 class testfrfrlocalizefrfrcookedtest baselocalizetest def testlocalizeself self testlocalize 50000 00 50000 00 self testlocalize 50000 00 50 000 00 groupingtrue if name main unittest main base class for tests using a real locale the locale test work fine on osx 10 6 i ronaldoussoren haven t had time yet to verify if tests work on osx 10 5 10 4 is known to be bad base class for tests using cooked localeconv values a cooked c locale a cooked en_us locale a cooked fr_fr locale with a space character as decimal separator and a non ascii currency symbol utility functions for formatting tests xxx there is a grouping padding bug when the thousands separator is empty but the grouping array contains values e g solaris 10 spaces in formatting string dots in formatting string padding asterisk formats test more in one general tests on locale format_string test number formatting with a real english locale test number formatting with a cooked en_us locale test number formatting with a cooked c locale test number formatting with a cooked fr_fr locale test string collation functions embedded null character embedded null character test string collation functions with a real english locale issue 18378 on at least macos setting lc_ctype to utf 8 is valid furthermore lc_ctype utf is used by the utf 8 locale coercing during interpreter startup on macos invoke getencoding to make sure it does not cause exceptions make sure it is valid when _locale getencoding is missing locale getencoding uses the python filesystem invoke getpreferredencoding to make sure it does not cause exceptions if encoding non empty make sure it is valid test crasher from bug 3303 crasher from bug 7419 issue 1813 setting and getting the locale under a turkish locale unsupported locale on this system bpo 37945 setlocale lc_ctype fails with getlocale lc_ctype and the tr_tr locale on windows getlocale builds a locale which is not recognize by setlocale
from decimal import Decimal
from test.support import verbose, is_android, is_emscripten, is_wasi
from test.support.warnings_helper import check_warnings
from test.support.import_helper import import_fresh_module
from unittest import mock
import unittest
import locale
import sys
import codecs


class BaseLocalizedTest(unittest.TestCase):
    
    
    

    @classmethod
    def setUpClass(cls):
        if sys.platform == 'darwin':
            import os
            tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", "en_US")
            if int(os.uname().release.split('.')[0]) < 10:
                
                
                
                raise unittest.SkipTest("Locale support on MacOSX is minimal")
        elif sys.platform.startswith("win"):
            tlocs = ("En", "English")
        else:
            tlocs = ("en_US.UTF-8", "en_US.ISO8859-1",
                     "en_US.US-ASCII", "en_US")
        try:
            oldlocale = locale.setlocale(locale.LC_NUMERIC)
            for tloc in tlocs:
                try:
                    locale.setlocale(locale.LC_NUMERIC, tloc)
                except locale.Error:
                    continue
                break
            else:
                raise unittest.SkipTest("Test locale not supported "
                                        "(tried %s)" % (', '.join(tlocs)))
            cls.enUS_locale = tloc
        finally:
            locale.setlocale(locale.LC_NUMERIC, oldlocale)

    def setUp(self):
        oldlocale = locale.setlocale(self.locale_type)
        self.addCleanup(locale.setlocale, self.locale_type, oldlocale)
        locale.setlocale(self.locale_type, self.enUS_locale)
        if verbose:
            print("testing with %r..." % self.enUS_locale, end=' ', flush=True)


class BaseCookedTest(unittest.TestCase):
    
    
    

    def setUp(self):
        locale._override_localeconv = self.cooked_values

    def tearDown(self):
        locale._override_localeconv = {}

class CCookedTest(BaseCookedTest):
    

    cooked_values = {
        'currency_symbol': '',
        'decimal_point': '.',
        'frac_digits': 127,
        'grouping': [],
        'int_curr_symbol': '',
        'int_frac_digits': 127,
        'mon_decimal_point': '',
        'mon_grouping': [],
        'mon_thousands_sep': '',
        'n_cs_precedes': 127,
        'n_sep_by_space': 127,
        'n_sign_posn': 127,
        'negative_sign': '',
        'p_cs_precedes': 127,
        'p_sep_by_space': 127,
        'p_sign_posn': 127,
        'positive_sign': '',
        'thousands_sep': ''
    }

class EnUSCookedTest(BaseCookedTest):
    

    cooked_values = {
        'currency_symbol': '$',
        'decimal_point': '.',
        'frac_digits': 2,
        'grouping': [3, 3, 0],
        'int_curr_symbol': 'USD ',
        'int_frac_digits': 2,
        'mon_decimal_point': '.',
        'mon_grouping': [3, 3, 0],
        'mon_thousands_sep': ',',
        'n_cs_precedes': 1,
        'n_sep_by_space': 0,
        'n_sign_posn': 1,
        'negative_sign': '-',
        'p_cs_precedes': 1,
        'p_sep_by_space': 0,
        'p_sign_posn': 1,
        'positive_sign': '',
        'thousands_sep': ','
    }


class FrFRCookedTest(BaseCookedTest):
    
    

    cooked_values = {
        'currency_symbol': '\u20ac',
        'decimal_point': ',',
        'frac_digits': 2,
        'grouping': [3, 3, 0],
        'int_curr_symbol': 'EUR ',
        'int_frac_digits': 2,
        'mon_decimal_point': ',',
        'mon_grouping': [3, 3, 0],
        'mon_thousands_sep': ' ',
        'n_cs_precedes': 0,
        'n_sep_by_space': 1,
        'n_sign_posn': 1,
        'negative_sign': '-',
        'p_cs_precedes': 0,
        'p_sep_by_space': 1,
        'p_sign_posn': 1,
        'positive_sign': '',
        'thousands_sep': ' '
    }


class BaseFormattingTest(object):
    
    
    

    def _test_format_string(self, format, value, out, **format_opts):
        self.assertEqual(
            locale.format_string(format, value, **format_opts), out)

    def _test_currency(self, value, out, **format_opts):
        self.assertEqual(locale.currency(value, **format_opts), out)


class EnUSNumberFormatting(BaseFormattingTest):
    
    

    def setUp(self):
        self.sep = locale.localeconv()['thousands_sep']

    def test_grouping(self):
        self._test_format_string("%f", 1024, grouping=1, out='1%s024.000000' % self.sep)
        self._test_format_string("%f", 102, grouping=1, out='102.000000')
        self._test_format_string("%f", -42, grouping=1, out='-42.000000')
        self._test_format_string("%+f", -42, grouping=1, out='-42.000000')

    def test_grouping_and_padding(self):
        self._test_format_string("%20.f", -42, grouping=1, out='-42'.rjust(20))
        if self.sep:
            self._test_format_string("%+10.f", -4200, grouping=1,
                out=('-4%s200' % self.sep).rjust(10))
            self._test_format_string("%-10.f", -4200, grouping=1,
                out=('-4%s200' % self.sep).ljust(10))

    def test_integer_grouping(self):
        self._test_format_string("%d", 4200, grouping=True, out='4%s200' % self.sep)
        self._test_format_string("%+d", 4200, grouping=True, out='+4%s200' % self.sep)
        self._test_format_string("%+d", -4200, grouping=True, out='-4%s200' % self.sep)

    def test_integer_grouping_and_padding(self):
        self._test_format_string("%10d", 4200, grouping=True,
            out=('4%s200' % self.sep).rjust(10))
        self._test_format_string("%-10d", -4200, grouping=True,
            out=('-4%s200' % self.sep).ljust(10))

    def test_simple(self):
        self._test_format_string("%f", 1024, grouping=0, out='1024.000000')
        self._test_format_string("%f", 102, grouping=0, out='102.000000')
        self._test_format_string("%f", -42, grouping=0, out='-42.000000')
        self._test_format_string("%+f", -42, grouping=0, out='-42.000000')

    def test_padding(self):
        self._test_format_string("%20.f", -42, grouping=0, out='-42'.rjust(20))
        self._test_format_string("%+10.f", -4200, grouping=0, out='-4200'.rjust(10))
        self._test_format_string("%-10.f", 4200, grouping=0, out='4200'.ljust(10))

    def test_complex_formatting(self):
        
        self._test_format_string("One million is %i", 1000000, grouping=1,
            out='One million is 1%s000%s000' % (self.sep, self.sep))
        self._test_format_string("One  million is %i", 1000000, grouping=1,
            out='One  million is 1%s000%s000' % (self.sep, self.sep))
        
        self._test_format_string(".%f.", 1000.0, out='.1000.000000.')
        
        if self.sep:
            self._test_format_string("-->  %10.2f", 4200, grouping=1,
                out='-->  ' + ('4%s200.00' % self.sep).rjust(10))
        
        self._test_format_string("%10.*f", (2, 1000), grouping=0,
            out='1000.00'.rjust(10))
        if self.sep:
            self._test_format_string("%*.*f", (10, 2, 1000), grouping=1,
                out=('1%s000.00' % self.sep).rjust(10))
        
        if self.sep:
            self._test_format_string("int %i float %.2f str %s",
                (1000, 1000.0, 'str'), grouping=1,
                out='int 1%s000 float 1%s000.00 str str' %
                (self.sep, self.sep))

        self._test_format_string("total=%i%%", 100, out='total=100%')
        self._test_format_string("newline: %i\n", 3, out='newline: 3\n')
        self._test_format_string("extra: %ii", 3, out='extra: 3i')


class TestLocaleFormatString(unittest.TestCase):
    

    def test_percent_escape(self):
        self.assertEqual(locale.format_string('%f%%', 1.0), '%f%%' % 1.0)
        self.assertEqual(locale.format_string('%d %f%%d', (1, 1.0)),
            '%d %f%%d' % (1, 1.0))
        self.assertEqual(locale.format_string('%(foo)s %%d', {'foo': 'bar'}),
            ('%(foo)s %%d' % {'foo': 'bar'}))

    def test_mapping(self):
        self.assertEqual(locale.format_string('%(foo)s bing.', {'foo': 'bar'}),
            ('%(foo)s bing.' % {'foo': 'bar'}))
        self.assertEqual(locale.format_string('%(foo)s', {'foo': 'bar'}),
            ('%(foo)s' % {'foo': 'bar'}))



class TestNumberFormatting(BaseLocalizedTest, EnUSNumberFormatting):
    

    locale_type = locale.LC_NUMERIC

    def setUp(self):
        BaseLocalizedTest.setUp(self)
        EnUSNumberFormatting.setUp(self)


class TestEnUSNumberFormatting(EnUSCookedTest, EnUSNumberFormatting):
    

    def setUp(self):
        EnUSCookedTest.setUp(self)
        EnUSNumberFormatting.setUp(self)

    def test_currency(self):
        self._test_currency(50000, "$50000.00")
        self._test_currency(50000, "$50,000.00", grouping=True)
        self._test_currency(50000, "USD 50,000.00",
            grouping=True, international=True)


class TestCNumberFormatting(CCookedTest, BaseFormattingTest):
    

    def test_grouping(self):
        self._test_format_string("%.2f", 12345.67, grouping=True, out='12345.67')

    def test_grouping_and_padding(self):
        self._test_format_string("%9.2f", 12345.67, grouping=True, out=' 12345.67')


class TestFrFRNumberFormatting(FrFRCookedTest, BaseFormattingTest):
    

    def test_decimal_point(self):
        self._test_format_string("%.2f", 12345.67, out='12345,67')

    def test_grouping(self):
        self._test_format_string("%.2f", 345.67, grouping=True, out='345,67')
        self._test_format_string("%.2f", 12345.67, grouping=True, out='12 345,67')

    def test_grouping_and_padding(self):
        self._test_format_string("%6.2f", 345.67, grouping=True, out='345,67')
        self._test_format_string("%7.2f", 345.67, grouping=True, out=' 345,67')
        self._test_format_string("%8.2f", 12345.67, grouping=True, out='12 345,67')
        self._test_format_string("%9.2f", 12345.67, grouping=True, out='12 345,67')
        self._test_format_string("%10.2f", 12345.67, grouping=True, out=' 12 345,67')
        self._test_format_string("%-6.2f", 345.67, grouping=True, out='345,67')
        self._test_format_string("%-7.2f", 345.67, grouping=True, out='345,67 ')
        self._test_format_string("%-8.2f", 12345.67, grouping=True, out='12 345,67')
        self._test_format_string("%-9.2f", 12345.67, grouping=True, out='12 345,67')
        self._test_format_string("%-10.2f", 12345.67, grouping=True, out='12 345,67 ')

    def test_integer_grouping(self):
        self._test_format_string("%d", 200, grouping=True, out='200')
        self._test_format_string("%d", 4200, grouping=True, out='4 200')

    def test_integer_grouping_and_padding(self):
        self._test_format_string("%4d", 4200, grouping=True, out='4 200')
        self._test_format_string("%5d", 4200, grouping=True, out='4 200')
        self._test_format_string("%10d", 4200, grouping=True, out='4 200'.rjust(10))
        self._test_format_string("%-4d", 4200, grouping=True, out='4 200')
        self._test_format_string("%-5d", 4200, grouping=True, out='4 200')
        self._test_format_string("%-10d", 4200, grouping=True, out='4 200'.ljust(10))

    def test_currency(self):
        euro = '\u20ac'
        self._test_currency(50000, "50000,00 " + euro)
        self._test_currency(50000, "50 000,00 " + euro, grouping=True)
        self._test_currency(50000, "50 000,00 EUR",
            grouping=True, international=True)


class TestCollation(unittest.TestCase):
    

    def test_strcoll(self):
        self.assertLess(locale.strcoll('a', 'b'), 0)
        self.assertEqual(locale.strcoll('a', 'a'), 0)
        self.assertGreater(locale.strcoll('b', 'a'), 0)
        
        self.assertRaises(ValueError, locale.strcoll, 'a\0', 'a')
        self.assertRaises(ValueError, locale.strcoll, 'a', 'a\0')

    def test_strxfrm(self):
        self.assertLess(locale.strxfrm('a'), locale.strxfrm('b'))
        
        self.assertRaises(ValueError, locale.strxfrm, 'a\0')


class TestEnUSCollation(BaseLocalizedTest, TestCollation):
    

    locale_type = locale.LC_ALL

    def setUp(self):
        enc = codecs.lookup(locale.getencoding() or 'ascii').name
        if enc not in ('utf-8', 'iso8859-1', 'cp1252'):
            raise unittest.SkipTest('encoding not suitable')
        if enc != 'iso8859-1' and (sys.platform == 'darwin' or is_android or
                                   sys.platform.startswith('freebsd')):
            raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs')
        BaseLocalizedTest.setUp(self)

    @unittest.skipIf(sys.platform.startswith('aix'),
                     'bpo-29972: broken test on AIX')
    @unittest.skipIf(
        is_emscripten or is_wasi,
        "musl libc issue on Emscripten/WASI, bpo-46390"
    )
    def test_strcoll_with_diacritic(self):
        self.assertLess(locale.strcoll('à', 'b'), 0)

    @unittest.skipIf(sys.platform.startswith('aix'),
                     'bpo-29972: broken test on AIX')
    @unittest.skipIf(
        is_emscripten or is_wasi,
        "musl libc issue on Emscripten/WASI, bpo-46390"
    )
    def test_strxfrm_with_diacritic(self):
        self.assertLess(locale.strxfrm('à'), locale.strxfrm('b'))


class NormalizeTest(unittest.TestCase):
    def check(self, localename, expected):
        self.assertEqual(locale.normalize(localename), expected, msg=localename)

    def test_locale_alias(self):
        for localename, alias in locale.locale_alias.items():
            with self.subTest(locale=(localename, alias)):
                self.check(localename, alias)

    def test_empty(self):
        self.check('', '')

    def test_c(self):
        self.check('c', 'C')
        self.check('posix', 'C')

    def test_english(self):
        self.check('en', 'en_US.ISO8859-1')
        self.check('EN', 'en_US.ISO8859-1')
        self.check('en.iso88591', 'en_US.ISO8859-1')
        self.check('en_US', 'en_US.ISO8859-1')
        self.check('en_us', 'en_US.ISO8859-1')
        self.check('en_GB', 'en_GB.ISO8859-1')
        self.check('en_US.UTF-8', 'en_US.UTF-8')
        self.check('en_US.utf8', 'en_US.UTF-8')
        self.check('en_US:UTF-8', 'en_US.UTF-8')
        self.check('en_US.ISO8859-1', 'en_US.ISO8859-1')
        self.check('en_US.US-ASCII', 'en_US.ISO8859-1')
        self.check('en_US.88591', 'en_US.ISO8859-1')
        self.check('en_US.885915', 'en_US.ISO8859-15')
        self.check('english', 'en_EN.ISO8859-1')
        self.check('english_uk.ascii', 'en_GB.ISO8859-1')

    def test_hyphenated_encoding(self):
        self.check('az_AZ.iso88599e', 'az_AZ.ISO8859-9E')
        self.check('az_AZ.ISO8859-9E', 'az_AZ.ISO8859-9E')
        self.check('tt_RU.koi8c', 'tt_RU.KOI8-C')
        self.check('tt_RU.KOI8-C', 'tt_RU.KOI8-C')
        self.check('lo_LA.cp1133', 'lo_LA.IBM-CP1133')
        self.check('lo_LA.ibmcp1133', 'lo_LA.IBM-CP1133')
        self.check('lo_LA.IBM-CP1133', 'lo_LA.IBM-CP1133')
        self.check('uk_ua.microsoftcp1251', 'uk_UA.CP1251')
        self.check('uk_ua.microsoft-cp1251', 'uk_UA.CP1251')
        self.check('ka_ge.georgianacademy', 'ka_GE.GEORGIAN-ACADEMY')
        self.check('ka_GE.GEORGIAN-ACADEMY', 'ka_GE.GEORGIAN-ACADEMY')
        self.check('cs_CZ.iso88592', 'cs_CZ.ISO8859-2')
        self.check('cs_CZ.ISO8859-2', 'cs_CZ.ISO8859-2')

    def test_euro_modifier(self):
        self.check('de_DE@euro', 'de_DE.ISO8859-15')
        self.check('en_US.ISO8859-15@euro', 'en_US.ISO8859-15')
        self.check('de_DE.utf8@euro', 'de_DE.UTF-8')

    def test_latin_modifier(self):
        self.check('be_BY.UTF-8@latin', 'be_BY.UTF-8@latin')
        self.check('sr_RS.UTF-8@latin', 'sr_RS.UTF-8@latin')
        self.check('sr_RS.UTF-8@latn', 'sr_RS.UTF-8@latin')

    def test_valencia_modifier(self):
        self.check('ca_ES.UTF-8@valencia', 'ca_ES.UTF-8@valencia')
        self.check('ca_ES@valencia', 'ca_ES.UTF-8@valencia')
        self.check('ca@valencia', 'ca_ES.ISO8859-1@valencia')

    def test_devanagari_modifier(self):
        self.check('ks_IN.UTF-8@devanagari', 'ks_IN.UTF-8@devanagari')
        self.check('ks_IN@devanagari', 'ks_IN.UTF-8@devanagari')
        self.check('ks@devanagari', 'ks_IN.UTF-8@devanagari')
        self.check('ks_IN.UTF-8', 'ks_IN.UTF-8')
        self.check('ks_IN', 'ks_IN.UTF-8')
        self.check('ks', 'ks_IN.UTF-8')
        self.check('sd_IN.UTF-8@devanagari', 'sd_IN.UTF-8@devanagari')
        self.check('sd_IN@devanagari', 'sd_IN.UTF-8@devanagari')
        self.check('sd@devanagari', 'sd_IN.UTF-8@devanagari')
        self.check('sd_IN.UTF-8', 'sd_IN.UTF-8')
        self.check('sd_IN', 'sd_IN.UTF-8')
        self.check('sd', 'sd_IN.UTF-8')

    def test_euc_encoding(self):
        self.check('ja_jp.euc', 'ja_JP.eucJP')
        self.check('ja_jp.eucjp', 'ja_JP.eucJP')
        self.check('ko_kr.euc', 'ko_KR.eucKR')
        self.check('ko_kr.euckr', 'ko_KR.eucKR')
        self.check('zh_cn.euc', 'zh_CN.eucCN')
        self.check('zh_tw.euc', 'zh_TW.eucTW')
        self.check('zh_tw.euctw', 'zh_TW.eucTW')

    def test_japanese(self):
        self.check('ja', 'ja_JP.eucJP')
        self.check('ja.jis', 'ja_JP.JIS7')
        self.check('ja.sjis', 'ja_JP.SJIS')
        self.check('ja_jp', 'ja_JP.eucJP')
        self.check('ja_jp.ajec', 'ja_JP.eucJP')
        self.check('ja_jp.euc', 'ja_JP.eucJP')
        self.check('ja_jp.eucjp', 'ja_JP.eucJP')
        self.check('ja_jp.iso-2022-jp', 'ja_JP.JIS7')
        self.check('ja_jp.iso2022jp', 'ja_JP.JIS7')
        self.check('ja_jp.jis', 'ja_JP.JIS7')
        self.check('ja_jp.jis7', 'ja_JP.JIS7')
        self.check('ja_jp.mscode', 'ja_JP.SJIS')
        self.check('ja_jp.pck', 'ja_JP.SJIS')
        self.check('ja_jp.sjis', 'ja_JP.SJIS')
        self.check('ja_jp.ujis', 'ja_JP.eucJP')
        self.check('ja_jp.utf8', 'ja_JP.UTF-8')
        self.check('japan', 'ja_JP.eucJP')
        self.check('japanese', 'ja_JP.eucJP')
        self.check('japanese-euc', 'ja_JP.eucJP')
        self.check('japanese.euc', 'ja_JP.eucJP')
        self.check('japanese.sjis', 'ja_JP.SJIS')
        self.check('jp_jp', 'ja_JP.eucJP')


class TestMiscellaneous(unittest.TestCase):
    def test_defaults_UTF8(self):
        
        
        
        import _locale
        import os

        self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8'))

        if hasattr(_locale, '_getdefaultlocale'):
            orig_getlocale = _locale._getdefaultlocale
            del _locale._getdefaultlocale
        else:
            orig_getlocale = None

        orig_env = {}
        try:
            for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'):
                if key in os.environ:
                    orig_env[key] = os.environ[key]
                    del os.environ[key]

            os.environ['LC_CTYPE'] = 'UTF-8'

            with check_warnings(('', DeprecationWarning)):
                self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8'))

        finally:
            for k in orig_env:
                os.environ[k] = orig_env[k]

            if 'LC_CTYPE' not in orig_env:
                del os.environ['LC_CTYPE']

            if orig_getlocale is not None:
                _locale._getdefaultlocale = orig_getlocale

    def test_getencoding(self):
        
        enc = locale.getencoding()
        self.assertIsInstance(enc, str)
        self.assertNotEqual(enc, "")
        
        codecs.lookup(enc)

    def test_getencoding_fallback(self):
        
        
        encoding = 'FALLBACK_ENCODING'
        with mock.patch.object(sys, 'getfilesystemencoding',
                               return_value=encoding):
            locale_fallback = import_fresh_module('locale', blocked=['_locale'])
            self.assertEqual(locale_fallback.getencoding(), encoding)

    def test_getpreferredencoding(self):
        
        enc = locale.getpreferredencoding()
        if enc:
            
            codecs.lookup(enc)

    def test_strcoll_3303(self):
        
        self.assertRaises(TypeError, locale.strcoll, "a", None)
        self.assertRaises(TypeError, locale.strcoll, b"a", None)

    def test_setlocale_category(self):
        locale.setlocale(locale.LC_ALL)
        locale.setlocale(locale.LC_TIME)
        locale.setlocale(locale.LC_CTYPE)
        locale.setlocale(locale.LC_COLLATE)
        locale.setlocale(locale.LC_MONETARY)
        locale.setlocale(locale.LC_NUMERIC)

        
        self.assertRaises(locale.Error, locale.setlocale, 12345)

    def test_getsetlocale_issue1813(self):
        
        oldlocale = locale.setlocale(locale.LC_CTYPE)
        self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale)
        try:
            locale.setlocale(locale.LC_CTYPE, 'tr_TR')
        except locale.Error:
            
            self.skipTest('test needs Turkish locale')
        loc = locale.getlocale(locale.LC_CTYPE)
        if verbose:
            print('testing with %a' % (loc,), end=' ', flush=True)
        try:
            locale.setlocale(locale.LC_CTYPE, loc)
        except locale.Error as exc:
            
            
            
            self.skipTest(f"setlocale(LC_CTYPE, {loc!r}) failed: {exc!r}")
        self.assertEqual(loc, locale.getlocale(locale.LC_CTYPE))

    def test_invalid_locale_format_in_localetuple(self):
        with self.assertRaises(TypeError):
            locale.setlocale(locale.LC_ALL, b'fi_FI')

    def test_invalid_iterable_in_localetuple(self):
        with self.assertRaises(TypeError):
            locale.setlocale(locale.LC_ALL, (b'not', b'valid'))


class BaseDelocalizeTest(BaseLocalizedTest):

    def _test_delocalize(self, value, out):
        self.assertEqual(locale.delocalize(value), out)

    def _test_atof(self, value, out):
        self.assertEqual(locale.atof(value), out)

    def _test_atoi(self, value, out):
        self.assertEqual(locale.atoi(value), out)


class TestEnUSDelocalize(EnUSCookedTest, BaseDelocalizeTest):

    def test_delocalize(self):
        self._test_delocalize('50000.00', '50000.00')
        self._test_delocalize('50,000.00', '50000.00')

    def test_atof(self):
        self._test_atof('50000.00', 50000.)
        self._test_atof('50,000.00', 50000.)

    def test_atoi(self):
        self._test_atoi('50000', 50000)
        self._test_atoi('50,000', 50000)


class TestCDelocalizeTest(CCookedTest, BaseDelocalizeTest):

    def test_delocalize(self):
        self._test_delocalize('50000.00', '50000.00')

    def test_atof(self):
        self._test_atof('50000.00', 50000.)

    def test_atoi(self):
        self._test_atoi('50000', 50000)


class TestfrFRDelocalizeTest(FrFRCookedTest, BaseDelocalizeTest):

    def test_delocalize(self):
        self._test_delocalize('50000,00', '50000.00')
        self._test_delocalize('50 000,00', '50000.00')

    def test_atof(self):
        self._test_atof('50000,00', 50000.)
        self._test_atof('50 000,00', 50000.)

    def test_atoi(self):
        self._test_atoi('50000', 50000)
        self._test_atoi('50 000', 50000)


class BaseLocalizeTest(BaseLocalizedTest):

    def _test_localize(self, value, out, grouping=False):
        self.assertEqual(locale.localize(value, grouping=grouping), out)


class TestEnUSLocalize(EnUSCookedTest, BaseLocalizeTest):

    def test_localize(self):
        self._test_localize('50000.00', '50000.00')
        self._test_localize(
            '{0:.16f}'.format(Decimal('1.15')), '1.1500000000000000')


class TestCLocalize(CCookedTest, BaseLocalizeTest):

    def test_localize(self):
        self._test_localize('50000.00', '50000.00')


class TestfrFRLocalize(FrFRCookedTest, BaseLocalizeTest):

    def test_localize(self):
        self._test_localize('50000.00', '50000,00')
        self._test_localize('50000.00', '50 000,00', grouping=True)


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