diff -r 9a0b46132876 Lib/_bootlocale.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/_bootlocale.py Fri Oct 11 23:48:13 2013 +0200 @@ -0,0 +1,29 @@ +"""A subset of the locale module used at interpreter startup, in order to +get a critical function (getpreferredencoding()) with minimal import +dependencies. + +Don't import directly from third-party code; use the `locale` module instead! +""" + +import _locale +import sys + +if sys.platform.startswith("win"): + def getpreferredencoding(do_setlocale=True): + if do_setlocale: + raise ValueError("do_setlocale must be False") + return _locale._getdefaultlocale()[1] + +elif hasattr(_locale, 'CODESET'): + def getpreferredencoding(do_setlocale=True): + if do_setlocale: + raise ValueError("do_setlocale must be False") + result = _locale.nl_langinfo(_locale.CODESET) + if not result and sys.platform == 'darwin': + # See above for explanation + result = 'UTF-8' + return result + +else: + from locale import getpreferredencoding + diff -r 9a0b46132876 Lib/_pyio.py --- a/Lib/_pyio.py Fri Oct 11 21:40:55 2013 +0200 +++ b/Lib/_pyio.py Fri Oct 11 23:48:13 2013 +0200 @@ -1487,12 +1487,12 @@ class TextIOWrapper(TextIOBase): pass if encoding is None: try: - import locale + import _bootlocale except ImportError: - # Importing locale may fail if Python is being built + # Importing _bootlocale may fail if Python is being built encoding = "ascii" else: - encoding = locale.getpreferredencoding(False) + encoding = _bootlocale.getpreferredencoding(False) if not isinstance(encoding, str): raise ValueError("invalid encoding: %r" % encoding) diff -r 9a0b46132876 Lib/site.py --- a/Lib/site.py Fri Oct 11 21:40:55 2013 +0200 +++ b/Lib/site.py Fri Oct 11 23:48:13 2013 +0200 @@ -426,8 +426,8 @@ def aliasmbcs(): 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 -r 9a0b46132876 Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py Fri Oct 11 21:40:55 2013 +0200 +++ b/Lib/test/test_subprocess.py Fri Oct 11 23:48:13 2013 +0200 @@ -883,8 +883,9 @@ class ProcessTestCase(BaseTestCase): # # 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 @@ class ProcessTestCase(BaseTestCase): 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 @@ class ProcessTestCase(BaseTestCase): 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 -r 9a0b46132876 Modules/_io/_iomodule.c --- a/Modules/_io/_iomodule.c Fri Oct 11 21:40:55 2013 +0200 +++ b/Modules/_io/_iomodule.c Fri Oct 11 23:48:13 2013 +0200 @@ -546,7 +546,7 @@ PyObject * } 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);