]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Patch #612627: Add encoding attribute to file objects, and determine
authorMartin v. Löwis <martin@v.loewis.de>
Sat, 10 May 2003 07:10:12 +0000 (07:10 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Sat, 10 May 2003 07:10:12 +0000 (07:10 +0000)
the terminal encoding on Windows and Unix.

Doc/api/concrete.tex
Doc/lib/libstdtypes.tex
Include/fileobject.h
Misc/NEWS
Objects/fileobject.c
Python/sysmodule.c

index f8cbc2834b1590ed6625add86ac64cbccff4c179..2c14596f5619f28d83f3b4e4da119241420d09cc 100644 (file)
@@ -2029,6 +2029,12 @@ implementation detail and may change in future releases of Python.
   creation.
 \end{cfuncdesc}
 
+\begin{cfuncdesc}{int}{PyFile_Encoding}{PyFileObject *p, char *enc}
+  Set the file's encoding for Unicode output to \var{enc}. Return
+  1 on success and 0 on failure.
+  \versionadded{2.3}
+\end{cfuncdesc}
+
 \begin{cfuncdesc}{int}{PyFile_SoftSpace}{PyObject *p, int newflag}
   This function exists for internal use by the interpreter.  Sets the
   \member{softspace} attribute of \var{p} to \var{newflag} and
index 04cdbcab9f0ca5931d3313ad22af31d63f3c1e39..951d0884ccb882566c0448abcee7b16f0c96b3fe 100644 (file)
@@ -1372,6 +1372,20 @@ read-only attribute; the \method{close()} method changes the value.
 It may not be available on all file-like objects.
 \end{memberdesc}
 
+\begin{memberdesc}[file]{encoding}
+The encoding that this file uses. When Unicode strings are written
+to a file, they will be converted to byte strings using this encoding.
+In addition, when the file is connected to a terminal, the attribute
+gives the encoding that the terminal is likely to use (that 
+information might be incorrect if the user has misconfigured the 
+terminal). The attribute is read-only and may not be present on
+all file-like objects. It may also be \code{None}, in which case
+the file uses the system default encoding for converting Unicode
+strings.
+
+\versionadded{2.3}
+\end{memberdesc}
+
 \begin{memberdesc}[file]{mode}
 The I/O mode for the file.  If the file was created using the
 \function{open()} built-in function, this will be the value of the
index c351b4d09d39ce76c9f29cc4808ca1d44e13c58b..e2053df2e4f7c1427c0fd78ae98f49a6ad3d84b7 100644 (file)
@@ -24,6 +24,7 @@ typedef struct {
        int f_newlinetypes;     /* Types of newlines seen */
        int f_skipnextlf;       /* Skip next \n */
 #endif
+       PyObject *f_encoding;
 } PyFileObject;
 
 PyAPI_DATA(PyTypeObject) PyFile_Type;
@@ -33,6 +34,7 @@ PyAPI_DATA(PyTypeObject) PyFile_Type;
 
 PyAPI_FUNC(PyObject *) PyFile_FromString(char *, char *);
 PyAPI_FUNC(void) PyFile_SetBufSize(PyObject *, int);
+PyAPI_FUNC(int) PyFile_SetEncoding(PyObject *, const char *);
 PyAPI_FUNC(PyObject *) PyFile_FromFile(FILE *, char *, char *,
                                              int (*)(FILE *));
 PyAPI_FUNC(FILE *) PyFile_AsFile(PyObject *);
index b94339103cdfbb6f863d56a38fd582aee4d7831f..098145a880483ebaadd5d01f39a454c160a3ae9b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.3 beta 2?
 Core and builtins
 -----------------
 
+- The encoding attribute has been added for file objects, and set to
+  the terminal encoding on Unix and Windows.
+
 - The softspace attribute of file objects became read-only by oversight.
   It's writable again.
 
index 92cfa5b35a94d0185e1f2d7cb44d26b95f59ce82..40ce759f5840424cd52d7c6d4eab8a9c675c8598 100644 (file)
@@ -116,6 +116,7 @@ fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
 
        Py_DECREF(f->f_name);
        Py_DECREF(f->f_mode);
+       Py_DECREF(f->f_encoding);
 #ifdef Py_USING_UNICODE
        if (wname)
                f->f_name = PyUnicode_FromObject(wname);
@@ -133,7 +134,9 @@ fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
        f->f_newlinetypes = NEWLINE_UNKNOWN;
        f->f_skipnextlf = 0;
 #endif
-
+       Py_INCREF(Py_None);
+       f->f_encoding = Py_None;
+       
        if (f->f_name == NULL || f->f_mode == NULL)
                return NULL;
        f->f_fp = fp;
@@ -302,6 +305,21 @@ PyFile_SetBufSize(PyObject *f, int bufsize)
        }
 }
 
+/* Set the encoding used to output Unicode strings.
+   Returh 1 on success, 0 on failure. */
+
+int
+PyFile_SetEncoding(PyObject *f, const char *enc)
+{
+       PyFileObject *file = (PyFileObject*)f;
+       PyObject *str = PyString_FromString(enc);
+       if (!str)
+               return 0;
+       Py_DECREF(file->f_encoding);
+       file->f_encoding = str;
+       return 1;
+}
+
 static PyObject *
 err_closed(void)
 {
@@ -323,6 +341,7 @@ file_dealloc(PyFileObject *f)
        }
        Py_XDECREF(f->f_name);
        Py_XDECREF(f->f_mode);
+       Py_XDECREF(f->f_encoding);
        drop_readahead(f);
        f->ob_type->tp_free((PyObject *)f);
 }
@@ -1667,6 +1686,8 @@ static PyMemberDef file_memberlist[] = {
         "file mode ('r', 'U', 'w', 'a', possibly with 'b' or '+' added)"},
        {"name",        T_OBJECT,       OFF(f_name),    RO,
         "file name"},
+       {"encoding",    T_OBJECT,       OFF(f_encoding),        RO,
+        "file encoding"},
        /* getattr(f, "closed") is implemented without this table */
        {NULL}  /* Sentinel */
 };
@@ -1851,6 +1872,8 @@ file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                ((PyFileObject *)self)->f_name = not_yet_string;
                Py_INCREF(not_yet_string);
                ((PyFileObject *)self)->f_mode = not_yet_string;
+               Py_INCREF(Py_None);
+               ((PyFileObject *)self)->f_encoding = Py_None;
        }
        return self;
 }
@@ -2034,11 +2057,28 @@ PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
        }
        else if (PyFile_Check(f)) {
                FILE *fp = PyFile_AsFile(f);
+               PyObject *enc = ((PyFileObject*)f)->f_encoding;
+               int result;
                if (fp == NULL) {
                        err_closed();
                        return -1;
                }
+#ifdef Py_USING_UNICODE
+                if (PyUnicode_Check(v) && enc != Py_None) {
+                       char *cenc = PyString_AS_STRING(enc);
+                       value = PyUnicode_AsEncodedString(v, cenc, "strict");
+                       if (value == NULL)
+                               return -1;
+               } else {
+                       value = v;
+                       Py_INCREF(value);
+               }
+               result = PyObject_Print(value, fp, flags);
+               Py_DECREF(value);
+               return result;
+#else
                return PyObject_Print(v, fp, flags);
+#endif
        }
        writer = PyObject_GetAttrString(f, "write");
        if (writer == NULL)
index d06d18a98b40fe48409ebe198dacc5536e128679..edbc2bf5805b2d40dd79922cc785bf25ce4da645 100644 (file)
@@ -36,6 +36,15 @@ extern const char *PyWin_DLLVersionString;
 #include <unixlib.h>
 #endif
 
+#ifdef MS_WINDOWS
+#include <windows.h>
+#endif
+
+#ifdef HAVE_LANGINFO_H
+#include <locale.h>
+#include <langinfo.h>
+#endif
+
 PyObject *
 PySys_GetObject(char *name)
 {
@@ -881,6 +890,12 @@ _PySys_Init(void)
        PyObject *m, *v, *sysdict;
        PyObject *sysin, *sysout, *syserr;
        char *s;
+#ifdef MS_WINDOWS
+       char buf[10];
+#endif
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+       char *oldloc, *codeset;
+#endif
 
        m = Py_InitModule3("sys", sys_methods, sys_doc);
        sysdict = PyModule_GetDict(m);
@@ -890,6 +905,34 @@ _PySys_Init(void)
        syserr = PyFile_FromFile(stderr, "<stderr>", "w", NULL);
        if (PyErr_Occurred())
                return NULL;
+#ifdef MS_WINDOWS
+       if(isatty(_fileno(stdin))){
+               sprintf(buf, "cp%d", GetConsoleCP());
+               if (!PyFile_SetEncoding(sysin, buf))
+                       return NULL;
+       }
+       if(isatty(_fileno(stdout))) {
+               sprintf(buf, "cp%d", GetConsoleOutputCP());
+               if (!PyFile_SetEncoding(sysout, buf))
+                       return NULL;
+       }
+#endif
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+       oldloc = setlocale(LC_CTYPE, 0);
+       setlocale(LC_CTYPE, "");
+       codeset = nl_langinfo(CODESET);
+       setlocale(LC_CTYPE, oldloc);
+       if(codeset && isatty(fileno(stdin))){
+               if (!PyFile_SetEncoding(sysin, codeset))
+                       return NULL;
+       }
+       if(codeset && isatty(fileno(stdout))) {
+               if (!PyFile_SetEncoding(sysout, codeset))
+                       return NULL;
+       }
+#endif
+       
        PyDict_SetItemString(sysdict, "stdin", sysin);
        PyDict_SetItemString(sysdict, "stdout", sysout);
        PyDict_SetItemString(sysdict, "stderr", syserr);