]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Set sys.stdout.encoding properly.
authorMartin v. Löwis <martin@v.loewis.de>
Sat, 11 Aug 2007 14:02:14 +0000 (14:02 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Sat, 11 Aug 2007 14:02:14 +0000 (14:02 +0000)
Always set LC_CTYPE on interpreter startup.
Add device_encoding function.

Lib/io.py
Modules/_localemodule.c
Modules/posixmodule.c
Python/pythonrun.c

index 1ee465a91f2bbfa8dd9a1442cd20dbe73ec9ae37..4ee7cef7198eb960839e60cb11774bcec5f4ec0d 100644 (file)
--- a/Lib/io.py
+++ b/Lib/io.py
@@ -971,8 +971,13 @@ class TextIOWrapper(TextIOBase):
         if newline not in (None, "\n", "\r\n"):
             raise ValueError("illegal newline value: %r" % (newline,))
         if encoding is None:
-            # XXX This is questionable
-            encoding = sys.getfilesystemencoding() or "latin-1"
+            try:
+                encoding = os.device_encoding(buffer.fileno())
+            except AttributeError:
+                pass
+            if encoding is None:
+                import locale
+                encoding = locale.getpreferredencoding()
 
         self.buffer = buffer
         self._encoding = encoding
index 6f063fba740a2bf705bdd6d259044cff6a26bc49..233cf02ea819d6b6b57f4a98e8bcaa727533e1fd 100644 (file)
@@ -1,5 +1,5 @@
 /***********************************************************
-Copyright (C) 1997, 2002, 2003 Martin von Loewis
+Copyright (C) 1997, 2002, 2003, 2007 Martin von Loewis
 
 Permission to use, copy, modify, and distribute this software and its
 documentation for any purpose and without fee is hereby granted,
@@ -562,7 +562,8 @@ PyLocale_nl_langinfo(PyObject* self, PyObject* args)
             /* Check NULL as a workaround for GNU libc's returning NULL
                instead of an empty string for nl_langinfo(ERA).  */
             const char *result = nl_langinfo(item);
-            return PyString_FromString(result != NULL ? result : "");
+            /* XXX may have to convert this to wcs first. */
+            return PyUnicode_FromString(result != NULL ? result : "");
         }
     PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
     return NULL;
index 9d4d14f4d01b5300ac66ddcbb954fe477865c6a3..61ac4e64825f44db98ad4c9b53504c5c14b5a1c4 100644 (file)
@@ -92,6 +92,10 @@ corresponding Unix manual entries for more information on calls.");
 #include <sys/loadavg.h>
 #endif
 
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
 /* Various compilers have only certain posix functions */
 /* XXX Gosh I wish these were all moved into pyconfig.h */
 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
@@ -6581,6 +6585,43 @@ win32_urandom(PyObject *self, PyObject *args)
 }
 #endif
 
+PyDoc_STRVAR(device_encoding__doc__,
+"device_encoding(fd) -> str\n\n\
+Return a string describing the encoding of the device\n\
+if the output is a terminal; else return None.");
+
+static PyObject *
+device_encoding(PyObject *self, PyObject *args)
+{
+       int fd;
+       if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
+               return NULL;
+       if (!isatty(fd)) {
+               Py_INCREF(Py_None);
+               return Py_None;
+       }
+#if defined(MS_WINDOWS) || defined(MS_WIN64)
+       if (fd == 0) {
+               char buf[100];
+               sprintf(buf, "cp%d", GetConsoleCP());
+               return PyUnicode_FromString(buf);
+       }
+       if (fd == 1 || fd == 2) {
+               char buf[100];
+               sprintf(buf, "cp%d", GetConsoleOutputCP());
+               return PyUnicode_FromString(buf);
+       }
+#elif defined(CODESET)
+       {
+               char *codeset = nl_langinfo(CODESET);
+               if (codeset)
+                       return PyUnicode_FromString(codeset);
+       }
+#endif
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
 #ifdef __VMS
 /* Use openssl random routine */
 #include <openssl/rand.h>
@@ -6793,6 +6834,7 @@ static PyMethodDef posix_methods[] = {
 #endif /* HAVE_TCSETPGRP */
        {"open",        posix_open, METH_VARARGS, posix_open__doc__},
        {"close",       posix_close, METH_VARARGS, posix_close__doc__},
+       {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
        {"dup",         posix_dup, METH_VARARGS, posix_dup__doc__},
        {"dup2",        posix_dup2, METH_VARARGS, posix_dup2__doc__},
        {"lseek",       posix_lseek, METH_VARARGS, posix_lseek__doc__},
index bb69b1914214fa60b67d8a95736c2f4d6d146cae..cc0926a00485511fff1a8db9ad3977a944a57bcb 100644 (file)
@@ -154,7 +154,6 @@ Py_InitializeEx(int install_sigs)
        char *p;
 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
        char *codeset;
-       char *saved_locale;
 #endif
        extern void _Py_ReadyTypes(void);
 
@@ -162,6 +161,13 @@ Py_InitializeEx(int install_sigs)
                return;
        initialized = 1;
 
+#ifdef HAVE_SETLOCALE
+       /* Set up the LC_CTYPE locale, so we can obtain
+          the locale's charset without having to switch
+          locales. */
+       setlocale(LC_CTYPE, "");
+#endif
+
        if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
                Py_DebugFlag = add_flag(Py_DebugFlag, p);
        if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
@@ -254,8 +260,6 @@ Py_InitializeEx(int install_sigs)
           initialized by other means. Also set the encoding of
           stdin and stdout if these are terminals.  */
 
-       saved_locale = strdup(setlocale(LC_CTYPE, NULL));
-       setlocale(LC_CTYPE, "");
        codeset = nl_langinfo(CODESET);
        if (codeset && *codeset) {
                PyObject *enc = PyCodec_Encoder(codeset);
@@ -268,8 +272,6 @@ Py_InitializeEx(int install_sigs)
                }
        } else
                codeset = NULL;
-       setlocale(LC_CTYPE, saved_locale);
-       free(saved_locale);
 
        if (codeset) {
                if (!Py_FileSystemDefaultEncoding)