[Python-checkins] cpython: Issue #9548: Add a minimal "_bootlocale" module that is imported by the _io

antoine.pitrou python-checkins at python.org
Sat Oct 12 00:15:05 CEST 2013


http://hg.python.org/cpython/rev/fbbf8b160e8d
changeset:   86212:fbbf8b160e8d
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sat Oct 12 00:13:50 2013 +0200
summary:
  Issue #9548: Add a minimal "_bootlocale" module that is imported by the _io module instead of the full locale module.

files:
  Lib/_bootlocale.py          |  34 +++++++++++++++++++++++++
  Lib/locale.py               |  21 +++-----------
  Lib/site.py                 |   4 +-
  Lib/test/test_subprocess.py |   7 ++--
  Misc/NEWS                   |   3 ++
  Modules/_io/_iomodule.c     |   2 +-
  6 files changed, 49 insertions(+), 22 deletions(-)


diff --git a/Lib/_bootlocale.py b/Lib/_bootlocale.py
new file mode 100644
--- /dev/null
+++ b/Lib/_bootlocale.py
@@ -0,0 +1,34 @@
+"""A minimal subset of the locale module used at interpreter startup
+(imported by the _io module), in order to reduce startup time.
+
+Don't import directly from third-party code; use the `locale` module instead!
+"""
+
+import sys
+import _locale
+
+if sys.platform.startswith("win"):
+    def getpreferredencoding(do_setlocale=True):
+        return _locale._getdefaultlocale()[1]
+else:
+    try:
+        _locale.CODESET
+    except ImportError:
+        def getpreferredencoding(do_setlocale=True):
+            # This path for legacy systems needs the more complex
+            # getdefaultlocale() function, import the full locale module.
+            import locale
+            return locale.getpreferredencoding(do_setlocale)
+    else:
+        def getpreferredencoding(do_setlocale=True):
+            assert not do_setlocale
+            result = _locale.nl_langinfo(_locale.CODESET)
+            if not result and sys.platform == 'darwin':
+                # nl_langinfo can return an empty string
+                # when the setting has an invalid value.
+                # Default to UTF-8 in that case because
+                # UTF-8 is the default charset on OSX and
+                # returning nothing will crash the
+                # interpreter.
+                result = 'UTF-8'
+            return result
diff --git a/Lib/locale.py b/Lib/locale.py
--- a/Lib/locale.py
+++ b/Lib/locale.py
@@ -554,8 +554,8 @@
     # On Win32, this will return the ANSI code page
     def getpreferredencoding(do_setlocale = True):
         """Return the charset that the user is likely using."""
-        import _locale
-        return _locale._getdefaultlocale()[1]
+        import _bootlocale
+        return _bootlocale.getpreferredencoding(False)
 else:
     # On Unix, if CODESET is available, use that.
     try:
@@ -574,27 +574,16 @@
         def getpreferredencoding(do_setlocale = True):
             """Return the charset that the user is likely using,
             according to the system configuration."""
+            import _bootlocale
             if do_setlocale:
                 oldloc = setlocale(LC_CTYPE)
                 try:
                     setlocale(LC_CTYPE, "")
                 except Error:
                     pass
-                result = nl_langinfo(CODESET)
-                if not result and sys.platform == 'darwin':
-                    # nl_langinfo can return an empty string
-                    # when the setting has an invalid value.
-                    # Default to UTF-8 in that case because
-                    # UTF-8 is the default charset on OSX and
-                    # returning nothing will crash the
-                    # interpreter.
-                    result = 'UTF-8'
+            result = _bootlocale.getpreferredencoding(False)
+            if do_setlocale:
                 setlocale(LC_CTYPE, oldloc)
-            else:
-                result = nl_langinfo(CODESET)
-                if not result and sys.platform == 'darwin':
-                    # See above for explanation
-                    result = 'UTF-8'
             return result
 
 
diff --git a/Lib/site.py b/Lib/site.py
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -426,8 +426,8 @@
     while they are always available as "mbcs" in each locale. Make
     them usable by aliasing to "mbcs" in such a case."""
     if sys.platform == 'win32':
-        import locale, codecs
-        enc = locale.getdefaultlocale()[1]
+        import _bootlocale, codecs
+        enc = _bootlocale.getpreferredencoding(False)
         if enc.startswith('cp'):            # "cp***" ?
             try:
                 codecs.lookup(enc)
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -883,8 +883,9 @@
         #
         # UTF-16 and UTF-32-BE are sufficient to check both with BOM and
         # without, and UTF-16 and UTF-32.
+        import _bootlocale
         for encoding in ['utf-16', 'utf-32-be']:
-            old_getpreferredencoding = locale.getpreferredencoding
+            old_getpreferredencoding = _bootlocale.getpreferredencoding
             # Indirectly via io.TextIOWrapper, Popen() defaults to
             # locale.getpreferredencoding(False) and earlier in Python 3.2 to
             # locale.getpreferredencoding().
@@ -895,7 +896,7 @@
                     encoding)
             args = [sys.executable, '-c', code]
             try:
-                locale.getpreferredencoding = getpreferredencoding
+                _bootlocale.getpreferredencoding = getpreferredencoding
                 # We set stdin to be non-None because, as of this writing,
                 # a different code path is used when the number of pipes is
                 # zero or one.
@@ -904,7 +905,7 @@
                                          stdout=subprocess.PIPE)
                 stdout, stderr = popen.communicate(input='')
             finally:
-                locale.getpreferredencoding = old_getpreferredencoding
+                _bootlocale.getpreferredencoding = old_getpreferredencoding
             self.assertEqual(stdout, '1\n2\n3\n4')
 
     def test_no_leaking(self):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -36,6 +36,9 @@
 Library
 -------
 
+- Issue #9548: Add a minimal "_bootlocale" module that is imported by the
+  _io module instead of the full locale module.
+
 - Issue #18764: remove the 'print' alias for the PDB 'p' command so that it no
   longer shadows the print function.
 
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -546,7 +546,7 @@
         }
         Py_CLEAR(state->locale_module);
     }
-    mod = PyImport_ImportModule("locale");
+    mod = PyImport_ImportModule("_bootlocale");
     if (mod == NULL)
         return NULL;
     state->locale_module = PyWeakref_NewRef(mod, NULL);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list