Issue #14153 Create _Py_device_encoding() to prevent _io from having to import

the os module.
This commit is contained in:
Brett Cannon 2012-02-29 18:31:31 -05:00
parent 54c32032aa
commit efb00c0cc1
7 changed files with 70 additions and 45 deletions

View File

@ -5,6 +5,8 @@
extern "C" { extern "C" {
#endif #endif
PyAPI_FUNC(PyObject *) _Py_device_encoding(int);
PyAPI_FUNC(wchar_t *) _Py_char2wchar( PyAPI_FUNC(wchar_t *) _Py_char2wchar(
const char *arg, const char *arg,
size_t *size); size_t *size);

View File

@ -22,6 +22,8 @@ import asynchat
import socket import socket
import itertools import itertools
import stat import stat
import locale
import codecs
try: try:
import threading import threading
except ImportError: except ImportError:
@ -1424,6 +1426,22 @@ class FSEncodingTests(unittest.TestCase):
self.assertEqual(os.fsdecode(bytesfn), fn) self.assertEqual(os.fsdecode(bytesfn), fn)
class DeviceEncodingTests(unittest.TestCase):
def test_bad_fd(self):
# Return None when an fd doesn't actually exist.
self.assertIsNone(os.device_encoding(123456))
@unittest.skipUnless(sys.platform.startswith('win') or
(hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET')),
'test requires either Windows or nl_langinfo(CODESET)')
def test_device_encoding(self):
encoding = os.device_encoding(0)
self.assertIsNotNone(encoding)
self.assertTrue(codecs.lookup(encoding))
class PidTests(unittest.TestCase): class PidTests(unittest.TestCase):
@unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid") @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
def test_getppid(self): def test_getppid(self):
@ -1923,6 +1941,7 @@ def test_main():
Win32KillTests, Win32KillTests,
Win32SymlinkTests, Win32SymlinkTests,
FSEncodingTests, FSEncodingTests,
DeviceEncodingTests,
PidTests, PidTests,
LoginTests, LoginTests,
LinkTests, LinkTests,

View File

@ -537,7 +537,6 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
_PyIO_State *state = IO_MOD_STATE(mod); _PyIO_State *state = IO_MOD_STATE(mod);
if (!state->initialized) if (!state->initialized)
return 0; return 0;
Py_VISIT(state->os_module);
if (state->locale_module != NULL) { if (state->locale_module != NULL) {
Py_VISIT(state->locale_module); Py_VISIT(state->locale_module);
} }
@ -551,7 +550,6 @@ iomodule_clear(PyObject *mod) {
_PyIO_State *state = IO_MOD_STATE(mod); _PyIO_State *state = IO_MOD_STATE(mod);
if (!state->initialized) if (!state->initialized)
return 0; return 0;
Py_CLEAR(state->os_module);
if (state->locale_module != NULL) if (state->locale_module != NULL)
Py_CLEAR(state->locale_module); Py_CLEAR(state->locale_module);
Py_CLEAR(state->unsupported_operation); Py_CLEAR(state->unsupported_operation);
@ -595,11 +593,6 @@ PyInit__io(void)
state = IO_MOD_STATE(m); state = IO_MOD_STATE(m);
state->initialized = 0; state->initialized = 0;
/* put os in the module state */
state->os_module = PyImport_ImportModule("os");
if (state->os_module == NULL)
goto fail;
#define ADD_TYPE(type, name) \ #define ADD_TYPE(type, name) \
if (PyType_Ready(type) < 0) \ if (PyType_Ready(type) < 0) \
goto fail; \ goto fail; \
@ -725,7 +718,6 @@ PyInit__io(void)
return m; return m;
fail: fail:
Py_XDECREF(state->os_module);
Py_XDECREF(state->unsupported_operation); Py_XDECREF(state->unsupported_operation);
Py_DECREF(m); Py_DECREF(m);
return NULL; return NULL;

View File

@ -124,7 +124,6 @@ extern PyModuleDef _PyIO_Module;
typedef struct { typedef struct {
int initialized; int initialized;
PyObject *os_module;
PyObject *locale_module; PyObject *locale_module;
PyObject *unsupported_operation; PyObject *unsupported_operation;

View File

@ -14,7 +14,6 @@
_Py_IDENTIFIER(close); _Py_IDENTIFIER(close);
_Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(_dealloc_warn);
_Py_IDENTIFIER(decode); _Py_IDENTIFIER(decode);
_Py_IDENTIFIER(device_encoding);
_Py_IDENTIFIER(fileno); _Py_IDENTIFIER(fileno);
_Py_IDENTIFIER(flush); _Py_IDENTIFIER(flush);
_Py_IDENTIFIER(getpreferredencoding); _Py_IDENTIFIER(getpreferredencoding);
@ -875,9 +874,13 @@ textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
} }
} }
else { else {
self->encoding = _PyObject_CallMethodId(state->os_module, int fd = (int) PyLong_AsLong(fileno);
&PyId_device_encoding, Py_DECREF(fileno);
"N", fileno); if (fd == -1 && PyErr_Occurred()) {
goto error;
}
self->encoding = _Py_device_encoding(fd);
if (self->encoding == NULL) if (self->encoding == NULL)
goto error; goto error;
else if (!PyUnicode_Check(self->encoding)) else if (!PyUnicode_Check(self->encoding))

View File

@ -9326,35 +9326,11 @@ static PyObject *
device_encoding(PyObject *self, PyObject *args) device_encoding(PyObject *self, PyObject *args)
{ {
int fd; int fd;
#if defined(MS_WINDOWS) || defined(MS_WIN64)
UINT cp;
#endif
if (!PyArg_ParseTuple(args, "i:device_encoding", &fd)) if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
return NULL; return NULL;
if (!_PyVerify_fd(fd) || !isatty(fd)) {
Py_INCREF(Py_None); return _Py_device_encoding(fd);
return Py_None;
}
#if defined(MS_WINDOWS) || defined(MS_WIN64)
if (fd == 0)
cp = GetConsoleCP();
else if (fd == 1 || fd == 2)
cp = GetConsoleOutputCP();
else
cp = 0;
/* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
has no console */
if (cp != 0)
return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
#elif defined(CODESET)
{
char *codeset = nl_langinfo(CODESET);
if (codeset != NULL && codeset[0] != 0)
return PyUnicode_FromString(codeset);
}
#endif
Py_INCREF(Py_None);
return Py_None;
} }
#ifdef __VMS #ifdef __VMS

View File

@ -3,6 +3,40 @@
# include <windows.h> # include <windows.h>
#endif #endif
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
PyObject *
_Py_device_encoding(int fd)
{
#if defined(MS_WINDOWS) || defined(MS_WIN64)
UINT cp;
#endif
if (!_PyVerify_fd(fd) || !isatty(fd)) {
Py_RETURN_NONE;
}
#if defined(MS_WINDOWS) || defined(MS_WIN64)
if (fd == 0)
cp = GetConsoleCP();
else if (fd == 1 || fd == 2)
cp = GetConsoleOutputCP();
else
cp = 0;
/* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
has no console */
if (cp != 0)
return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
#elif defined(CODESET)
{
char *codeset = nl_langinfo(CODESET);
if (codeset != NULL && codeset[0] != 0)
return PyUnicode_FromString(codeset);
}
#endif
Py_RETURN_NONE;
}
#ifdef HAVE_STAT #ifdef HAVE_STAT
/* Decode a byte string from the locale encoding with the /* Decode a byte string from the locale encoding with the