Kaydet (Commit) c2e85bd4 authored tarafından Mark Hammond's avatar Mark Hammond

Patch 594001: PEP 277 - Unicode file name support for Windows NT.

üst eb287a26
...@@ -81,16 +81,37 @@ PyAPI_DATA(PyObject *) PyExc_FutureWarning; ...@@ -81,16 +81,37 @@ PyAPI_DATA(PyObject *) PyExc_FutureWarning;
PyAPI_FUNC(int) PyErr_BadArgument(void); PyAPI_FUNC(int) PyErr_BadArgument(void);
PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); PyAPI_FUNC(PyObject *) PyErr_NoMemory(void);
PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject(
PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *);
#ifdef Py_WIN_WIDE_FILENAMES
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename(
PyObject *, Py_UNICODE *);
#endif /* Py_WIN_WIDE_FILENAMES */
PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...) PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...)
Py_GCC_ATTRIBUTE((format(printf, 2, 3))); Py_GCC_ATTRIBUTE((format(printf, 2, 3)));
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(int, const char *); PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenameObject(
int, const char *);
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(
int, const char *);
#ifdef Py_WIN_WIDE_FILENAMES
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename(
int, const Py_UNICODE *);
#endif /* Py_WIN_WIDE_FILENAMES */
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int);
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject(
PyObject *,int, PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename(
PyObject *,int, const char *); PyObject *,int, const char *);
#ifdef Py_WIN_WIDE_FILENAMES
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename(
PyObject *,int, const Py_UNICODE *);
#endif /* Py_WIN_WIDE_FILENAMES */
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int);
#endif #endif /* MS_WINDOWS */
/* Export the old function so that the existing API remains available: */ /* Export the old function so that the existing API remains available: */
PyAPI_FUNC(void) PyErr_BadInternalCall(void); PyAPI_FUNC(void) PyErr_BadInternalCall(void);
......
...@@ -40,6 +40,10 @@ os.chmod(TESTFN_ENCODED, 0777) ...@@ -40,6 +40,10 @@ os.chmod(TESTFN_ENCODED, 0777)
os.chmod(TESTFN_UNICODE, 0777) os.chmod(TESTFN_UNICODE, 0777)
# Test rename # Test rename
try:
os.unlink(TESTFN_ENCODED + ".new")
except os.error:
pass
os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new") os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new")
os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED) os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED)
......
This diff is collapsed.
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
#include <windows.h> #include <windows.h>
#endif #endif
#ifdef _MSC_VER
/* Need GetVersion to see if on NT so safe to use _wfopen */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif /* _MSC_VER */
#ifdef macintosh #ifdef macintosh
#ifdef USE_GUSI #ifdef USE_GUSI
#define HAVE_FTRUNCATE #define HAVE_FTRUNCATE
...@@ -102,7 +108,7 @@ dircheck(PyFileObject* f) ...@@ -102,7 +108,7 @@ dircheck(PyFileObject* f)
static PyObject * static PyObject *
fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
int (*close)(FILE *)) int (*close)(FILE *), PyObject *wname)
{ {
assert(f != NULL); assert(f != NULL);
assert(PyFile_Check(f)); assert(PyFile_Check(f));
...@@ -110,6 +116,9 @@ fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, ...@@ -110,6 +116,9 @@ fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
Py_DECREF(f->f_name); Py_DECREF(f->f_name);
Py_DECREF(f->f_mode); Py_DECREF(f->f_mode);
if (wname)
f->f_name = PyUnicode_FromObject(wname);
else
f->f_name = PyString_FromString(name); f->f_name = PyString_FromString(name);
f->f_mode = PyString_FromString(mode); f->f_mode = PyString_FromString(mode);
...@@ -135,7 +144,12 @@ open_the_file(PyFileObject *f, char *name, char *mode) ...@@ -135,7 +144,12 @@ open_the_file(PyFileObject *f, char *name, char *mode)
{ {
assert(f != NULL); assert(f != NULL);
assert(PyFile_Check(f)); assert(PyFile_Check(f));
#ifdef MS_WINDOWS
/* windows ignores the passed name in order to support Unicode */
assert(f->f_name != NULL);
#else
assert(name != NULL); assert(name != NULL);
#endif
assert(mode != NULL); assert(mode != NULL);
assert(f->f_fp == NULL); assert(f->f_fp == NULL);
...@@ -156,7 +170,6 @@ open_the_file(PyFileObject *f, char *name, char *mode) ...@@ -156,7 +170,6 @@ open_the_file(PyFileObject *f, char *name, char *mode)
else else
#endif #endif
{ {
Py_BEGIN_ALLOW_THREADS
#ifdef WITH_UNIVERSAL_NEWLINES #ifdef WITH_UNIVERSAL_NEWLINES
if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
mode = "rb"; mode = "rb";
...@@ -168,9 +181,27 @@ open_the_file(PyFileObject *f, char *name, char *mode) ...@@ -168,9 +181,27 @@ open_the_file(PyFileObject *f, char *name, char *mode)
if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
mode = "r"; mode = "r";
#endif #endif
#ifdef MS_WINDOWS
if (PyUnicode_Check(f->f_name)) {
PyObject *wmode;
wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL);
if (f->f_name && wmode) {
Py_BEGIN_ALLOW_THREADS
/* PyUnicode_AS_UNICODE OK without thread
lock as it is a simple dereference. */
f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),
PyUnicode_AS_UNICODE(wmode));
Py_END_ALLOW_THREADS
}
Py_XDECREF(wmode);
}
#endif
if (NULL == f->f_fp && NULL != name) {
Py_BEGIN_ALLOW_THREADS
f->f_fp = fopen(name, mode); f->f_fp = fopen(name, mode);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
}
if (f->f_fp == NULL) { if (f->f_fp == NULL) {
#ifdef NO_FOPEN_ERRNO #ifdef NO_FOPEN_ERRNO
/* Metroworks only, wich does not always sets errno */ /* Metroworks only, wich does not always sets errno */
...@@ -201,7 +232,11 @@ open_the_file(PyFileObject *f, char *name, char *mode) ...@@ -201,7 +232,11 @@ open_the_file(PyFileObject *f, char *name, char *mode)
PyErr_Format(PyExc_IOError, "invalid mode: %s", PyErr_Format(PyExc_IOError, "invalid mode: %s",
mode); mode);
else else
#ifdef MS_WINDOWS
PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name);
#else
PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
#endif /* MS_WINDOWS */
f = NULL; f = NULL;
} }
if (f != NULL) if (f != NULL)
...@@ -215,7 +250,7 @@ PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *)) ...@@ -215,7 +250,7 @@ PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type, PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
NULL, NULL); NULL, NULL);
if (f != NULL) { if (f != NULL) {
if (fill_file_fields(f, fp, name, mode, close) == NULL) { if (fill_file_fields(f, fp, name, mode, close, NULL) == NULL) {
Py_DECREF(f); Py_DECREF(f);
f = NULL; f = NULL;
} }
...@@ -293,11 +328,24 @@ file_dealloc(PyFileObject *f) ...@@ -293,11 +328,24 @@ file_dealloc(PyFileObject *f)
static PyObject * static PyObject *
file_repr(PyFileObject *f) file_repr(PyFileObject *f)
{ {
if (PyUnicode_Check(f->f_name)) {
PyObject *ret = NULL;
PyObject *name;
name = PyUnicode_AsUnicodeEscapeString(f->f_name);
ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>",
f->f_fp == NULL ? "closed" : "open",
PyString_AsString(name),
PyString_AsString(f->f_mode),
f);
Py_XDECREF(name);
return ret;
} else {
return PyString_FromFormat("<%s file '%s', mode '%s' at %p>", return PyString_FromFormat("<%s file '%s', mode '%s' at %p>",
f->f_fp == NULL ? "closed" : "open", f->f_fp == NULL ? "closed" : "open",
PyString_AsString(f->f_name), PyString_AsString(f->f_name),
PyString_AsString(f->f_mode), PyString_AsString(f->f_mode),
f); f);
}
} }
static PyObject * static PyObject *
...@@ -1766,6 +1814,7 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -1766,6 +1814,7 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds)
char *name = NULL; char *name = NULL;
char *mode = "r"; char *mode = "r";
int bufsize = -1; int bufsize = -1;
int wideargument = 0;
assert(PyFile_Check(self)); assert(PyFile_Check(self));
if (foself->f_fp != NULL) { if (foself->f_fp != NULL) {
...@@ -1776,12 +1825,33 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -1776,12 +1825,33 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds)
Py_DECREF(closeresult); Py_DECREF(closeresult);
} }
#ifdef Py_WIN_WIDE_FILENAMES
if (GetVersion() < 0x80000000) { /* On NT, so wide API available */
PyObject *po;
if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",
kwlist, &po, &mode, &bufsize)) {
wideargument = 1;
if (fill_file_fields(foself, NULL, name, mode,
fclose, po) == NULL)
goto Error;
} else {
/* Drop the argument parsing error as narrow
strings are also valid. */
PyErr_Clear();
}
}
#endif
if (!wideargument) {
if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
Py_FileSystemDefaultEncoding, &name, Py_FileSystemDefaultEncoding,
&name,
&mode, &bufsize)) &mode, &bufsize))
return -1; return -1;
if (fill_file_fields(foself, NULL, name, mode, fclose) == NULL) if (fill_file_fields(foself, NULL, name, mode,
fclose, NULL) == NULL)
goto Error; goto Error;
}
if (open_the_file(foself, name, mode) == NULL) if (open_the_file(foself, name, mode) == NULL)
goto Error; goto Error;
PyFile_SetBufSize(self, bufsize); PyFile_SetBufSize(self, bufsize);
......
...@@ -400,6 +400,10 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ ...@@ -400,6 +400,10 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
Include/unicodeobject.h). */ Include/unicodeobject.h). */
#if Py_UNICODE_SIZE == 2 #if Py_UNICODE_SIZE == 2
#define HAVE_USABLE_WCHAR_T #define HAVE_USABLE_WCHAR_T
/* Define to indicate that the Python Unicode representation can be passed
as-is to Win32 Wide API. */
#define Py_WIN_WIDE_FILENAMES
#endif #endif
/* Use Python's own small-block memory-allocator. */ /* Use Python's own small-block memory-allocator. */
......
...@@ -259,7 +259,7 @@ PyErr_NoMemory(void) ...@@ -259,7 +259,7 @@ PyErr_NoMemory(void)
} }
PyObject * PyObject *
PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
{ {
PyObject *v; PyObject *v;
char *s; char *s;
...@@ -314,8 +314,8 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) ...@@ -314,8 +314,8 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename)
} }
#endif /* Unix/Windows */ #endif /* Unix/Windows */
#endif /* PLAN 9*/ #endif /* PLAN 9*/
if (filename != NULL) if (filenameObject != NULL)
v = Py_BuildValue("(iss)", i, s, filename); v = Py_BuildValue("(isO)", i, s, filenameObject);
else else
v = Py_BuildValue("(is)", i, s); v = Py_BuildValue("(is)", i, s);
if (v != NULL) { if (v != NULL) {
...@@ -329,18 +329,40 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) ...@@ -329,18 +329,40 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename)
} }
PyObject *
PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename)
{
PyObject *name = filename ? PyString_FromString(filename) : NULL;
PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_DECREF(name);
return result;
}
#ifdef Py_WIN_WIDE_FILENAMES
PyObject *
PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
#endif /* Py_WIN_WIDE_FILENAMES */
PyObject * PyObject *
PyErr_SetFromErrno(PyObject *exc) PyErr_SetFromErrno(PyObject *exc)
{ {
return PyErr_SetFromErrnoWithFilename(exc, NULL); return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* Windows specific error code handling */ /* Windows specific error code handling */
PyObject *PyErr_SetExcFromWindowsErrWithFilename( PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
PyObject *exc, PyObject *exc,
int ierr, int ierr,
const char *filename) PyObject *filenameObject)
{ {
int len; int len;
char *s; char *s;
...@@ -362,8 +384,8 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename( ...@@ -362,8 +384,8 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename(
/* remove trailing cr/lf and dots */ /* remove trailing cr/lf and dots */
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
s[--len] = '\0'; s[--len] = '\0';
if (filename != NULL) if (filenameObject != NULL)
v = Py_BuildValue("(iss)", err, s, filename); v = Py_BuildValue("(isO)", err, s, filenameObject);
else else
v = Py_BuildValue("(is)", err, s); v = Py_BuildValue("(is)", err, s);
if (v != NULL) { if (v != NULL) {
...@@ -374,6 +396,36 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename( ...@@ -374,6 +396,36 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename(
return NULL; return NULL;
} }
PyObject *PyErr_SetExcFromWindowsErrWithFilename(
PyObject *exc,
int ierr,
const char *filename)
{
PyObject *name = filename ? PyString_FromString(filename) : NULL;
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
ierr,
name);
Py_XDECREF(name);
return ret;
}
#ifdef Py_WIN_WIDE_FILENAMES
PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
PyObject *exc,
int ierr,
const Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
ierr,
name);
Py_XDECREF(name);
return ret;
}
#endif /* Py_WIN_WIDE_FILENAMES */
PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)
{ {
return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);
...@@ -388,9 +440,29 @@ PyObject *PyErr_SetFromWindowsErrWithFilename( ...@@ -388,9 +440,29 @@ PyObject *PyErr_SetFromWindowsErrWithFilename(
int ierr, int ierr,
const char *filename) const char *filename)
{ {
return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, PyObject *name = filename ? PyString_FromString(filename) : NULL;
ierr, filename); PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
PyExc_WindowsError,
ierr, name);
Py_XDECREF(result);
return result;
}
#ifdef Py_WIN_WIDE_FILENAMES
PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
int ierr,
const Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
PyExc_WindowsError,
ierr, name);
Py_XDECREF(result);
return result;
} }
#endif /* Py_WIN_WIDE_FILENAMES */
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
void void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment