diff -r c53d24ee3963 Lib/locale.py --- a/Lib/locale.py Sat Jul 25 02:45:18 2015 +0200 +++ b/Lib/locale.py Sat Jul 25 12:43:53 2015 +0200 @@ -484,6 +484,10 @@ return tuple(code.split('.')[:2]) elif code == 'C': return None, None + elif code == 'UTF-8': + # On MacOSX "LC_CTYPE=UTF-8" is a valid locale setting + # for getting UTF-8 handling for text. + return None, 'UTF-8' raise ValueError('unknown locale: %s' % localename) def _build_localename(localetuple): diff -r c53d24ee3963 Lib/test/test_locale.py --- a/Lib/test/test_locale.py Sat Jul 25 02:45:18 2015 +0200 +++ b/Lib/test/test_locale.py Sat Jul 25 12:43:53 2015 +0200 @@ -477,6 +477,38 @@ class TestMiscellaneous(unittest.TestCase): + def test_defaults_UTF8(self): + # Issue #18378: on (at least) OSX setting LC_CTYPE to "UTF-8" is + # valid. + 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' + + self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8')) + + finally: + for k in orig_env: + os.environ[k] = orig_env[k] + + if orig_getlocale is not None: + _locale._getdefaultlocale = orig_getlocale + def test_getpreferredencoding(self): # Invoke getpreferredencoding to make sure it does not cause exceptions. enc = locale.getpreferredencoding()