Set sys.stdout.encoding properly.

Always set LC_CTYPE on interpreter startup.
Add device_encoding function.
This commit is contained in:
Martin v. Löwis 2007-08-11 14:02:14 +00:00
parent 79c320898d
commit d1cd4d4176
4 changed files with 59 additions and 9 deletions

View File

@ -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

View 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;

View 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__},

View 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)