Issue #14153 Create _Py_device_encoding() to prevent _io from having to import
the os module.
This commit is contained in:
parent
54c32032aa
commit
efb00c0cc1
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
An implementation of the new I/O lib as defined by PEP 3116 - "New I/O"
|
An implementation of the new I/O lib as defined by PEP 3116 - "New I/O"
|
||||||
|
|
||||||
Classes defined here: UnsupportedOperation, BlockingIOError.
|
Classes defined here: UnsupportedOperation, BlockingIOError.
|
||||||
Functions defined here: open().
|
Functions defined here: open().
|
||||||
|
|
||||||
Mostly written by Amaury Forgeot d'Arc
|
Mostly written by Amaury Forgeot d'Arc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -510,7 +510,7 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
|
||||||
|
|
||||||
|
|
||||||
/* Basically the "n" format code with the ability to turn None into -1. */
|
/* Basically the "n" format code with the ability to turn None into -1. */
|
||||||
int
|
int
|
||||||
_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
|
_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
|
||||||
Py_ssize_t limit;
|
Py_ssize_t limit;
|
||||||
if (obj == Py_None) {
|
if (obj == Py_None) {
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -50,8 +50,8 @@ extern PyObject *_PyIncrementalNewlineDecoder_decode(
|
||||||
`*consumed`.
|
`*consumed`.
|
||||||
If not found, returns -1 and sets `*consumed` to the number of characters
|
If not found, returns -1 and sets `*consumed` to the number of characters
|
||||||
which can be safely put aside until another search.
|
which can be safely put aside until another search.
|
||||||
|
|
||||||
NOTE: for performance reasons, `end` must point to a NUL character ('\0').
|
NOTE: for performance reasons, `end` must point to a NUL character ('\0').
|
||||||
Otherwise, the function will scan further and return garbage. */
|
Otherwise, the function will scan further and return garbage. */
|
||||||
extern Py_ssize_t _PyIO_find_line_ending(
|
extern Py_ssize_t _PyIO_find_line_ending(
|
||||||
int translated, int universal, PyObject *readnl,
|
int translated, int universal, PyObject *readnl,
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue