]> granicus.if.org Git - python/commitdiff
Issue #14153 Create _Py_device_encoding() to prevent _io from having to import
authorBrett Cannon <brett@python.org>
Wed, 29 Feb 2012 23:31:31 +0000 (18:31 -0500)
committerBrett Cannon <brett@python.org>
Wed, 29 Feb 2012 23:31:31 +0000 (18:31 -0500)
the os module.

Include/fileutils.h
Lib/test/test_os.py
Modules/_io/_iomodule.c
Modules/_io/_iomodule.h
Modules/_io/textio.c
Modules/posixmodule.c
Python/fileutils.c

index 2fade9b95cd8364947a24c478569e86543abcc4d..7c18cf237852009bbdf6ceb65ab2228fd1ec8471 100644 (file)
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+PyAPI_FUNC(PyObject *) _Py_device_encoding(int);
+
 PyAPI_FUNC(wchar_t *) _Py_char2wchar(
     const char *arg,
     size_t *size);
index a0f13fd790b0bd6183d00b0f25e278b035ce8324..5959d1e31dc6772cbe8df0d85d70a0e600b49ba1 100644 (file)
@@ -22,6 +22,8 @@ import asynchat
 import socket
 import itertools
 import stat
+import locale
+import codecs
 try:
     import threading
 except ImportError:
@@ -1424,6 +1426,22 @@ class FSEncodingTests(unittest.TestCase):
             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):
     @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
     def test_getppid(self):
@@ -1923,6 +1941,7 @@ def test_main():
         Win32KillTests,
         Win32SymlinkTests,
         FSEncodingTests,
+        DeviceEncodingTests,
         PidTests,
         LoginTests,
         LinkTests,
index 9aad479e5b3f4bab508a8d2ac65fb77cbc303500..31eea3cd03ea6857eac55d014647fef4e32858b4 100644 (file)
@@ -1,9 +1,9 @@
 /*
     An implementation of the new I/O lib as defined by PEP 3116 - "New I/O"
-    
+
     Classes defined here: UnsupportedOperation, BlockingIOError.
     Functions defined here: open().
-    
+
     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. */
-int 
+int
 _PyIO_ConvertSsize_t(PyObject *obj, void *result) {
     Py_ssize_t limit;
     if (obj == Py_None) {
@@ -537,7 +537,6 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
     _PyIO_State *state = IO_MOD_STATE(mod);
     if (!state->initialized)
         return 0;
-    Py_VISIT(state->os_module);
     if (state->locale_module != NULL) {
         Py_VISIT(state->locale_module);
     }
@@ -551,7 +550,6 @@ iomodule_clear(PyObject *mod) {
     _PyIO_State *state = IO_MOD_STATE(mod);
     if (!state->initialized)
         return 0;
-    Py_CLEAR(state->os_module);
     if (state->locale_module != NULL)
         Py_CLEAR(state->locale_module);
     Py_CLEAR(state->unsupported_operation);
@@ -595,11 +593,6 @@ PyInit__io(void)
     state = IO_MOD_STATE(m);
     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) \
     if (PyType_Ready(type) < 0) \
         goto fail; \
@@ -725,7 +718,6 @@ PyInit__io(void)
     return m;
 
   fail:
-    Py_XDECREF(state->os_module);
     Py_XDECREF(state->unsupported_operation);
     Py_DECREF(m);
     return NULL;
index b3a8471bc57f652aa794c8ab5d71a06481c7fe3b..987aac80e59b85023cc3aeff5add79df92f0a783 100644 (file)
@@ -50,8 +50,8 @@ extern PyObject *_PyIncrementalNewlineDecoder_decode(
    `*consumed`.
    If not found, returns -1 and sets `*consumed` to the number of characters
    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. */
 extern Py_ssize_t _PyIO_find_line_ending(
     int translated, int universal, PyObject *readnl,
@@ -124,7 +124,6 @@ extern PyModuleDef _PyIO_Module;
 
 typedef struct {
     int initialized;
-    PyObject *os_module;
     PyObject *locale_module;
 
     PyObject *unsupported_operation;
index 79c64baeefffa77395b82473941f3c9e648f482a..833a52763961d17a1ab1f11ebadc9d10285d7a58 100644 (file)
@@ -14,7 +14,6 @@
 _Py_IDENTIFIER(close);
 _Py_IDENTIFIER(_dealloc_warn);
 _Py_IDENTIFIER(decode);
-_Py_IDENTIFIER(device_encoding);
 _Py_IDENTIFIER(fileno);
 _Py_IDENTIFIER(flush);
 _Py_IDENTIFIER(getpreferredencoding);
@@ -875,9 +874,13 @@ textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
             }
         }
         else {
-            self->encoding = _PyObject_CallMethodId(state->os_module,
-                                                    &PyId_device_encoding,
-                                                    "N", fileno);
+            int fd = (int) PyLong_AsLong(fileno);
+            Py_DECREF(fileno);
+            if (fd == -1 && PyErr_Occurred()) {
+                goto error;
+            }
+
+            self->encoding = _Py_device_encoding(fd);
             if (self->encoding == NULL)
                 goto error;
             else if (!PyUnicode_Check(self->encoding))
index dbace1a8911ffdf2e788451a4a55064b33dd9af7..628b0b9463cddd330b56d730d5c44be3d9747fe4 100644 (file)
@@ -9326,35 +9326,11 @@ static PyObject *
 device_encoding(PyObject *self, PyObject *args)
 {
     int fd;
-#if defined(MS_WINDOWS) || defined(MS_WIN64)
-    UINT cp;
-#endif
+
     if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
         return NULL;
-    if (!_PyVerify_fd(fd) || !isatty(fd)) {
-        Py_INCREF(Py_None);
-        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;
+
+    return _Py_device_encoding(fd);
 }
 
 #ifdef __VMS
index 8993c8c49742bbdd9953ab7e73be607a6e74d2ae..501cb8c8d6e01d7929135b3a08c10d1c33aba300 100644 (file)
@@ -3,6 +3,40 @@
 #  include <windows.h>
 #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
 
 /* Decode a byte string from the locale encoding with the