]> granicus.if.org Git - python/commitdiff
- merged setlocale and set_locale. the internal setlocale
authorFredrik Lundh <fredrik@pythonware.com>
Sun, 9 Jul 2000 17:12:58 +0000 (17:12 +0000)
committerFredrik Lundh <fredrik@pythonware.com>
Sun, 9 Jul 2000 17:12:58 +0000 (17:12 +0000)
  function is overridden by a python version which accepts
  *either* a string (old behaviour) or a locale tuple.

- renamed a few methods (for consistency):

        get_locale => getlocale
        get_default_locale => getdefaultlocale
        set_to_default => resetlocale (!)

- the _locale implementation module can now implement
  an optional _getdefaultlocale function.  if that function
  isn't available, a POSIX-based approach is used (checking
  LANG and other environment variables, as usual).

(patch #100765)

Lib/locale.py

index 437755e5435b3fcc8ed830189a3fbd35b6e66af4..47f5c4e0386a9e1b38a6c0340d6243e5b70fa9f3 100644 (file)
 
 """
 
-import string
+import string, sys
 
-### Load C lib locale APIs or use an emulation
+# Try importing the _locale module.
+#
+# If this fails, fall back on a basic 'C' locale emulation.
+#
 
 try:
+
     from _locale import *
 
 except ImportError:
 
+    # Locale emulation
+
     CHAR_MAX = 127
     LC_ALL = 6
     LC_COLLATE = 3
@@ -31,46 +37,46 @@ except ImportError:
     Error = ValueError
 
     def localeconv():
-        """ localeconv() -> dict. 
+        """ localeconv() -> dict.
             Returns numeric and monetary locale-specific parameters.
         """
         # 'C' locale default values
         return {'grouping': [127],
                 'currency_symbol': '',
                 'n_sign_posn': 127,
-                'p_cs_precedes': 127, 
-                'n_cs_precedes': 127, 
-                'mon_grouping': [], 
+                'p_cs_precedes': 127,
+                'n_cs_precedes': 127,
+                'mon_grouping': [],
                 'n_sep_by_space': 127,
                 'decimal_point': '.',
                 'negative_sign': '',
                 'positive_sign': '',
-                'p_sep_by_space': 127, 
+                'p_sep_by_space': 127,
                 'int_curr_symbol': '',
-                'p_sign_posn': 127, 
+                'p_sign_posn': 127,
                 'thousands_sep': '',
-                'mon_thousands_sep': '', 
-                'frac_digits': 127, 
+                'mon_thousands_sep': '',
+                'frac_digits': 127,
                 'mon_decimal_point': '',
                 'int_frac_digits': 127}
-    
+
     def setlocale(category, value=None):
-        """ setlocale(integer,string=None) -> string. 
+        """ setlocale(integer,string=None) -> string.
             Activates/queries locale processing.
         """
         if value is not None and \
            value is not 'C':
-            raise Error,'_locale emulation only supports "C" locale'
+            raise Error, '_locale emulation only supports "C" locale'
         return 'C'
 
     def strcoll(a,b):
-        """ strcoll(string,string) -> int. 
+        """ strcoll(string,string) -> int.
             Compares two strings according to the locale.
         """
         return cmp(a,b)
 
     def strxfrm(s):
-        """ strxfrm(string) -> string. 
+        """ strxfrm(string) -> string.
             Returns a string that behaves for cmp locale-aware.
         """
         return s
@@ -86,7 +92,7 @@ def _group(s):
     if not grouping:return s
     result=""
     while s and grouping:
-        # if grouping is -1, we are done 
+        # if grouping is -1, we are done
         if grouping[0]==CHAR_MAX:
             break
         # 0: re-use last group ad infinitum
@@ -107,7 +113,7 @@ def _group(s):
 
 def format(f,val,grouping=0):
     """Formats a value in the same way that the % formatting would use,
-    but takes the current locale into account. 
+    but takes the current locale into account.
     Grouping is applied if the third parameter is true."""
     result = f % val
     fields = string.split(result, ".")
@@ -118,8 +124,8 @@ def format(f,val,grouping=0):
     elif len(fields)==1:
         return fields[0]
     else:
-        raise Error,"Too many decimal points in result string"
-    
+        raise Error, "Too many decimal points in result string"
+
 def str(val):
     """Convert float to integer, taking the locale into account."""
     return format("%.12g",val)
@@ -135,7 +141,7 @@ def atof(str,func=string.atof):
     dd = localeconv()['decimal_point']
     if dd:
         s=string.split(str,dd)
-        str=string.join(s,'.')
+        str=string.join(s, '.')
     #finally, parse the string
     return func(str)
 
@@ -144,17 +150,22 @@ def atoi(str):
     return atof(str,string.atoi)
 
 def _test():
-    setlocale(LC_ALL,"")
+    setlocale(LC_ALL, "")
     #do grouping
-    s1=format("%d",123456789,1)
-    print s1,"is",atoi(s1)
+    s1=format("%d", 123456789,1)
+    print s1, "is", atoi(s1)
     #standard formatting
     s1=str(3.14)
-    print s1,"is",atof(s1)
+    print s1, "is", atof(s1)
 
 ### Locale name aliasing engine
 
 # Author: Marc-Andre Lemburg, mal@lemburg.com
+# Various tweaks by Fredrik Lundh <effbot@telia.com>
+
+# store away the low-level version of setlocale (it's
+# overridden below)
+_setlocale = setlocale
 
 def normalize(localename):
 
@@ -229,7 +240,7 @@ def _parse_localename(localename):
     elif code == 'C':
         return None, None
     else:
-        raise ValueError,'unknown locale: %s' % localename
+        raise ValueError, 'unknown locale: %s' % localename
     return l
 
 def _build_localename(localetuple):
@@ -247,15 +258,15 @@ def _build_localename(localetuple):
         return language
     else:
         return language + '.' + encoding
-    
-def get_default(envvars=('LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')):
+
+def getdefaultlocale(envvars=('LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')):
 
     """ Tries to determine the default locale settings and returns
         them as tuple (language code, encoding).
 
         According to POSIX, a program which has not called
-        setlocale(LC_ALL,"") runs using the portable 'C' locale.
-        Calling setlocale(LC_ALL,"") lets it use the default locale as
+        setlocale(LC_ALL, "") runs using the portable 'C' locale.
+        Calling setlocale(LC_ALL, "") lets it use the default locale as
         defined by the LANG variable. Since we don't want to interfere
         with the current locale setting we thus emulate the behaviour
         in the way described above.
@@ -271,6 +282,17 @@ def get_default(envvars=('LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')):
         be determined.
 
     """
+    try:
+        # check if it's supported by the _locale module
+        import _locale
+        code, encoding = _locale._getdefaultlocale()
+        if sys.platform == "win32" and code and code[:2] == "0x":
+            # map windows language identifier to language name
+            code = windows_locale.get(int(code, 0))
+        return code, encoding
+    except (ImportError, NameError):
+        pass
+    # fall back on POSIX behaviour
     import os
     lookup = os.environ.get
     for variable in envvars:
@@ -281,7 +303,10 @@ def get_default(envvars=('LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG')):
         localename = 'C'
     return _parse_localename(localename)
 
-def get_locale(category=LC_CTYPE):
+# compatibility
+get_default = getdefaultlocale
+
+def getlocale(category=LC_CTYPE):
 
     """ Returns the current setting for the given locale category as
         tuple (language code, encoding).
@@ -294,34 +319,36 @@ def get_locale(category=LC_CTYPE):
         be determined.
 
     """
-    localename = setlocale(category)
+    localename = _setlocale(category)
     if category == LC_ALL and ';' in localename:
-        raise TypeError,'category LC_ALL is not supported'
+        raise TypeError, 'category LC_ALL is not supported'
     return _parse_localename(localename)
 
-def set_locale(localetuple, category=LC_ALL):
+def setlocale(category, locale=None):
 
-    """ Set the locale according to the localetuple (language code,
-        encoding) as returned by get_locale() and get_default().
+    """ Set the locale for the given category.  The locale can be
+        a string, a locale tuple (language code, encoding), or None.
 
-        The given codes are passed through the locale aliasing engine
-        before being given to setlocale() for processing.
+        Locale tuples are converted to strings the locale aliasing
+        engine.  Locale strings are passed directly to the C lib.
 
-        category may be given as one of the LC_* values. It defaults
-        to LC_ALL.
+        category may be given as one of the LC_* values.
 
     """
-    setlocale(category, normalize(_build_localename(localetuple)))
+    if locale and type(locale) is not type(""):
+        # convert to string
+        locale = normalize(_build_localename(locale))
+    return _setlocale(category, locale)
 
-def set_to_default(category=LC_ALL):
+def resetlocale(category=LC_ALL):
 
     """ Sets the locale for category to the default setting.
 
         The default setting is determined by calling
-        get_default(). category defaults to LC_ALL.
-        
+        getdefaultlocale(). category defaults to LC_ALL.
+
     """
-    setlocale(category, _build_localename(get_default()))
+    _setlocale(category, _build_localename(getdefaultlocale()))
 
 ### Database
 #
@@ -329,47 +356,47 @@ def set_to_default(category=LC_ALL):
 # comes with X11 and then hand edited removing the explicit encoding
 # definitions and adding some more aliases. The file is usually
 # available as /usr/lib/X11/locale/locale.alias.
-#    
+#
 
 #
 # The encoding_alias table maps lowercase encoding alias names to C
 # locale encoding names (case-sensitive).
 #
 encoding_alias = {
-        '437':                                 'C',
-        'c':                           'C',
-        'iso8859':                     'ISO8859-1',
-        '8859':                        'ISO8859-1',
-        '88591':                       'ISO8859-1',
-        'ascii':                       'ISO8859-1',
-        'en':                          'ISO8859-1',
-        'iso88591':                    'ISO8859-1',
-        'iso_8859-1':                  'ISO8859-1',
-        '885915':                      'ISO8859-15',
-        'iso885915':                   'ISO8859-15',
-        'iso_8859-15':                         'ISO8859-15',
-        'iso8859-2':                   'ISO8859-2',
-        'iso88592':                    'ISO8859-2',
-        'iso_8859-2':                  'ISO8859-2',
-        'iso88595':                    'ISO8859-5',
-        'iso88596':                    'ISO8859-6',
-        'iso88597':                    'ISO8859-7',
-        'iso88598':                    'ISO8859-8',
-        'iso88599':                    'ISO8859-9',
-        'iso-2022-jp':                         'JIS7',
-        'jis':                                 'JIS7',
-        'jis7':                        'JIS7',
-        'sjis':                        'SJIS',
-        'tis620':                      'TACTIS',
-        'ajec':                        'eucJP',
-        'eucjp':                       'eucJP',
-        'ujis':                        'eucJP',
-        'utf-8':                       'utf',
-        'utf8':                        'utf',
-        'utf8@ucs4':                   'utf',
+        '437':                          'C',
+        'c':                            'C',
+        'iso8859':                      'ISO8859-1',
+        '8859':                         'ISO8859-1',
+        '88591':                        'ISO8859-1',
+        'ascii':                        'ISO8859-1',
+        'en':                           'ISO8859-1',
+        'iso88591':                     'ISO8859-1',
+        'iso_8859-1':                   'ISO8859-1',
+        '885915':                       'ISO8859-15',
+        'iso885915':                    'ISO8859-15',
+        'iso_8859-15':                  'ISO8859-15',
+        'iso8859-2':                    'ISO8859-2',
+        'iso88592':                     'ISO8859-2',
+        'iso_8859-2':                   'ISO8859-2',
+        'iso88595':                     'ISO8859-5',
+        'iso88596':                     'ISO8859-6',
+        'iso88597':                     'ISO8859-7',
+        'iso88598':                     'ISO8859-8',
+        'iso88599':                     'ISO8859-9',
+        'iso-2022-jp':                  'JIS7',
+        'jis':                          'JIS7',
+        'jis7':                         'JIS7',
+        'sjis':                         'SJIS',
+        'tis620':                       'TACTIS',
+        'ajec':                         'eucJP',
+        'eucjp':                        'eucJP',
+        'ujis':                         'eucJP',
+        'utf-8':                        'utf',
+        'utf8':                         'utf',
+        'utf8@ucs4':                    'utf',
 }
 
-#    
+#
 # The locale_alias table maps lowercase alias names to C locale names
 # (case-sensitive). Encodings are always separated from the locale
 # name using a dot ('.'); they should only be given in case the
@@ -561,6 +588,46 @@ locale_alias = {
         'zh_tw.euc':                     'zh_TW.eucTW',
 }
 
+#
+# this maps windows language identifiers (as used on Windows 95 and
+# earlier) to locale strings.
+#
+# NOTE: this mapping is incomplete.  If your language is missing, send
+# a note with the missing language identifier and the suggested locale
+# code to Fredrik Lundh <effbot@telia.com>.  Thanks /F
+
+windows_locale = {
+    0x0404: "zh_TW", # Chinese (Taiwan)
+    0x0804: "zh_CN", # Chinese (PRC)
+    0x0406: "da_DK", # Danish
+    0x0413: "nl_NL", # Dutch (Netherlands)
+    0x0409: "en_US", # English (United States)
+    0x0809: "en_UK", # English (United Kingdom)
+    0x0c09: "en_AU", # English (Australian)
+    0x1009: "en_CA", # English (Canadian)
+    0x1409: "en_NZ", # English (New Zealand)
+    0x1809: "en_IE", # English (Ireland)
+    0x1c09: "en_ZA", # English (South Africa)
+    0x040b: "fi_FI", # Finnish
+    0x040c: "fr_FR", # French (Standard)
+    0x080c: "fr_BE", # French (Belgian)
+    0x0c0c: "fr_CA", # French (Canadian)
+    0x100c: "fr_CH", # French (Switzerland)
+    0x0407: "de_DE", # German (Standard)
+    0x0408: "el_GR", # Greek
+    0x040d: "iw_IL", # Hebrew
+    0x040f: "is_IS", # Icelandic
+    0x0410: "it_IT", # Italian (Standard)
+    0x0411: "ja_JA", # Japanese
+    0x0414: "no_NO", # Norwegian (Bokmal)
+    0x0816: "pt_PT", # Portuguese (Standard)
+    0x0c0a: "es_ES", # Spanish (Modern Sort)
+    0x0441: "sw_KE", # Swahili (Kenya)
+    0x041d: "sv_SE", # Swedish
+    0x081d: "sv_FI", # Swedish (Finland)
+    0x041f: "tr_TR", # Turkish
+}
+
 def _print_locale():
 
     """ Test function.
@@ -573,9 +640,9 @@ def _print_locale():
     _init_categories()
     del categories['LC_ALL']
 
-    print 'Locale defaults as determined by get_default():'
+    print 'Locale defaults as determined by getdefaultlocale():'
     print '-'*72
-    lang, enc = get_default()
+    lang, enc = getdefaultlocale()
     print 'Language: ', lang or '(undefined)'
     print 'Encoding: ', enc or '(undefined)'
     print
@@ -583,40 +650,40 @@ def _print_locale():
     print 'Locale settings on startup:'
     print '-'*72
     for name,category in categories.items():
-        print name,'...'
-        lang, enc = get_locale(category)
+        print name, '...'
+        lang, enc = getlocale(category)
         print '   Language: ', lang or '(undefined)'
         print '   Encoding: ', enc or '(undefined)'
         print
 
-    set_to_default()
     print
-    print 'Locale settings after calling set_to_default():'
+    print 'Locale settings after calling resetlocale():'
     print '-'*72
+    resetlocale()
     for name,category in categories.items():
-        print name,'...'
-        lang, enc = get_locale(category)
+        print name, '...'
+        lang, enc = getlocale(category)
         print '   Language: ', lang or '(undefined)'
         print '   Encoding: ', enc or '(undefined)'
         print
-    
+
     try:
-        setlocale(LC_ALL,"")
+        setlocale(LC_ALL, "")
     except:
         print 'NOTE:'
-        print 'setlocale(LC_ALL,"") does not support the default locale'
+        print 'setlocale(LC_ALL, "") does not support the default locale'
         print 'given in the OS environment variables.'
     else:
         print
-        print 'Locale settings after calling setlocale(LC_ALL,""):'
+        print 'Locale settings after calling setlocale(LC_ALL, ""):'
         print '-'*72
         for name,category in categories.items():
-            print name,'...'
-            lang, enc = get_locale(category)
+            print name, '...'
+            lang, enc = getlocale(category)
             print '   Language: ', lang or '(undefined)'
             print '   Encoding: ', enc or '(undefined)'
             print
-    
+
 ###
 
 if __name__=='__main__':